函数就是最基本的一种代码抽象的方式。是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段

内嵌函数

Python内置了很多有用的函数,我们可以直接调用,比如print,abs,int,type等,具体可查看官网文档
https://docs.python.org/3/library/functions.html

定义函数

使用def关键字,依次写出函数名、括号,括号中为参数、冒号:、在缩进块中编写函数体、返回值

  1. def fun_name(params):
  2. fun_body

实例,编写一个求 绝对值 的函数

  1. def my_abs(x):
  2. if not isinstance(x, (int, float)):
  3. raise TypeError('bad operand type')
  4. if x >= 0:
  5. return x
  6. else:
  7. return -x
  8. mb_abs(1) # 1
  9. mb_abs(-3) # 3

函数参数

位置参数

positional argument 也称必备参数

  1. def square(a, b):
  2. return a ** b

参数a,b就是位置参数
在调用函数时,必须按顺序传入这两个参数

  1. >>> square(2,3) # 8
  2. >>> square(3,2) # 9
  3. >>> square(2) #TypeError: square() takes exactly two argument (1 given)

默认参数

default argument,特别的,默认参数要定义在位置参数之后,使用默认参数可以降低使用难度

  1. def square(a, b=2):
  2. return a ** b

调用函数时,如果没有传参数b,就使用默认值。

  1. >>>square(2) # 4
  2. >>>square(2, 3) # 8
  3. >>>square(2, b=3) # 8

可变参数

也称不定长参数,参数的个数是可变的,定义在常规参数(regular param 位置参数和默认参数)之后。
实际例子:对一组数据进行求和,先看普通的参数定义方法。

  1. def calc(numbers):
  2. sum = 0
  3. for n in numbers:
  4. sum = sum + n
  5. return sum
  6. # 调用时候,需要先组装出一个tuple或者list
  7. calc([1,2,3]) # 6
  8. calc((1,2,3,)) # 6

如果改用可变参数,这些可变参数在函数调用时自动组装为一个tuple

  1. def calc(*numbers):
  2. sum = 0
  3. for n in numbers: # 此处numbers是一个tuple
  4. sum = sum + n
  5. return sum
  6. calc(1,2,3) # 6
  7. calc() # 0
  8. nums = [1,2,3]
  9. calc(nums[0], nums[1], nums[2]) # 6
  10. calc(*[1,2,3]) # 6

关键字参数

类比可变参数,可变参数是在函数调用时自动组装成一个tuple。可关键字参数,而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
定义时,关键字参数要定义在可变参数之后

  1. def person(name, age, **kw):
  2. if kw:
  3. print(type(kw))
  4. print('name:', name, 'age:', age, 'other:', kw)
  5. person("tao", 20, work="QA") # name: tao age: 20 other: {'work': 'QA'}

命名关键字参数

关键字未限制输出的参数名,若需要对参数名做限制,需要命名关键字参数。
定义函数时,如果没有可变参数,需要使用特殊分隔符”*”

  1. def person(name, age=3, *, city, job):
  2. print('name:', name, 'age:', age, 'other:', city, job)
  1. def person(name, age=3, *args, city, job):
  2. print('name:', name, 'age:', age, "args", args, 'other:', city, job)

参数组合

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

函数返回值

变量的作用域

Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索

  1. def foo():
  2. b = 'hello'
  3. # Python中可以在函数内部再定义函数
  4. def bar():
  5. c = True
  6. print(a)
  7. print(b)
  8. print(c)
  9. bar()
  10. # print(c) # NameError: name 'c' is not defined
  11. if __name__ == '__main__':
  12. a = 100
  13. # print(b) # NameError: name 'b' is not defined
  14. foo()
  • 局部作用域 : 在函数内部定义的变量
  • 嵌套作用域 : 对于函数bar,变量b即为嵌套作用域
  • 全局作用域 : 变量a
  • 内置作用域 : inputprintint

局部变量

  1. def foo():
  2. a = 200
  3. print(a) # 200
  4. if __name__ == '__main__':
  5. a = 100
  6. foo()
  7. print(a) # 100,foo函数a是局部变量,不会继续去寻找全局变量,所以全局变量a不会被foo函数修改

全局变量

  1. def foo():
  2. global a
  3. a = 200
  4. print(a) # 200
  5. if __name__ == '__main__':
  6. a = 100
  7. foo()
  8. print(a) # 200

嵌套变量

  1. def foo():
  2. a = 200
  3. def change_a():
  4. nonlocal a #声明a为嵌套变量
  5. a = 300
  6. print(a)
  7. change_a() #300
  8. print(a) #300
  9. if __name__ == '__main__':
  10. a = 100
  11. foo()
  12. print(a) # 100

递归函数

如果一个函数在内部调用自身本身,这个函数就是递归函数。
实现阶乘

  1. def fact(n):
  2. if n==1:
  3. return 1
  4. return n * fact(n - 1)
  5. ===> fact(5)
  6. ===> 5 * fact(4)
  7. ===> 5 * (4 * fact(3))
  8. ===> 5 * (4 * (3 * fact(2)))
  9. ===> 5 * (4 * (3 * (2 * fact(1))))
  10. ===> 5 * (4 * (3 * (2 * 1)))
  11. ===> 5 * (4 * (3 * 2))
  12. ===> 5 * (4 * 6)
  13. ===> 5 * 24
  14. ===> 120

高阶函数

变量可以指向函数,函数名也是变量。
把函数作为参数传入,这样的函数称为高阶函数。

map

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

  1. >>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
  2. ['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduce

reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是: reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

  1. >>> from functools import reduce
  2. >>> def add(x, y):
  3. ... return x + y
  4. ...
  5. >>> reduce(add, [1, 3, 5, 7, 9])
  6. 25

filter

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素

  1. def is_odd(n):
  2. return n % 2 == 1
  3. list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))

sorted

它还可以接收一个key函数来实现自定义的排序,,例如按绝对值大小排序(abs)
sorted([36, 5, -12, 9, -21], key=abs, reverse=True)

  1. >>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
  2. ['Zoo', 'Credit', 'bob', 'about']

返回函数

闭包

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。
另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

匿名函数

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

  1. lambda [arg1 [,arg2,.....argn]]:expression
  • 实现

    1. sum = lambda x,y: x+y
  • 配合高阶函数

    1. sum = list