6.1 函数-None
6.2 函数和结构-None
6.3 自定义函数
>>> x = 1
>>> callable(x)
False
>>> def hello(name):
... return 'Hello, ' + name + '!'
>>> print(hello('Andrew'))
6.3.1 docstring (文档字符串 document string)
- docstring 可放置于 def 语句后,以及模块、类的开头;
- 当 docstring 置于 def 语句后时,作为函数的一部分存储;
>>> def square(x):
... 'Calculates the square of the number x.'
... return x * x
>>> square.__doc__
'Calculates the square of the number x.'
>>> help(square)
Help on function square in module __main__:
square(x)
Calculates the square of the number x.
6.3.2 函数返回值
- Python中,允许函数不包含 return 语句,允许 return 语句后无指定值;
- 若无指定返回值,则默认返回 None ;
- 若在多分支语句(if 等语句)中返回值,则应确保其他分支也返回值,以免调用者期望返回一个序列(举个例子)时,不小心返回了 None ;
6.4 参数
6.4.1 形参与实参-None
6.4.2 修改参数
- 参数存储在局部作用域内,在函数内修改变量,函数外部的变量不受影响;
- string、number、tuple是不可变对象,不能修改值,只能替换为新值;
>>> string1 = 'pan', 'han', 'qi'
>>> string1
('pan', 'han', 'qi')
>>> def change(n):
... n[0] = 'Mr.Gumby'
>>> names = ['Mrs.Entity', 'Mrs.Thing']
>>> change(names)
>>> names
['Mr.Gumby', 'Mrs.Thing']
>>> change(names[:])
>>> names
['Mrs.Entity', 'Mrs.Thing']
6.4.3 关键字参数与默认值
- positional argument(位置参数):实参的顺序与形参一致;
- 关键字参数:不关注参数传递的顺序;
- 定义函数时,无默认值的形参应在有默认值的形参之前,否则报错;
- 尽量避免同时使用 positional argument 和关键字参数;
>>> def hello_3(name, greeting = 'Hello'):
... print('{},{}'.format(greeting, name))
>>> hello_3('Andrew')
>>> def in_the_middle(x, *y, z):
>>> print(x, y, z)
>>> in_the_middle(1, 2, 3, 4, 5, z = 7)
1 (2, 3, 4, 5) 7
>>> def print_params_4(x, y, z = 3, *pospar, **keypar):
... print(x, y, z)
... print(pospar)
... print(keypar)
>>> print_params_4(1, 2, 3, 4, 5, 6, 7, foo = 1, bar = 2)
1 2 3
(4, 5, 6, 7)
{'foo': 1, 'bar': 2}
6.4.5 分配参数
- 用单个星号分配 tuple ;
- 用2个星号分配 dictionary ;
>>> def add(x, y):
... return x + y
>>> params = (1, 2)
>>> add(*params)
3
6.5 作用域
- 变量与值之间的关系:即命名空间 or 作用域;
- 除全局作用域外,每次函数调用时均创建一个命名空间;
- 函数内的局部变量与全局变量不在同一个命名空间内,因此重名无影响;
>>> def combine(parameter):
... print(parameter + globals()['parameter'])
>>> parameter = 'berry'
>>> combine('Shrub')
>>> def change_global():
... global x
... x = x + 1
- 作用域嵌套:函数2定义在函数1内部;
- 返回的函数携带着自身所在的环境和局部变量;
- 由于Python的嵌套作用域效果,可在内部函数中访问外部函数的局部作用域中的变量;
- 闭包:存储其所在作用域的函数;
- 使用关键字 nonlocal,可在内部函数中向外部函数的变量赋值;
>>> def multiplier(factor):
... def multiplyByFactor(number):
... return number * factor
... return multiplyByFactor
>>> double = multiplier(2)
>>> double(5)
10
>>> multiplier(5)(4)
20
6.6 递归
- 嵌套:在函数1中定义函数2;
- 递归:函数调用自身;
每次递归调用,均为新函数创建新的命名空间;
- 无穷递归:将在超过最大递归深度后(耗尽所有内存空间),导致程序终止并报错;
- 递归函数包含两部分:
基线条件:针对最小问题,直接返回一个值;
递归条件:在调用过程中不断简化问题,最终化为可用基线条件解决的最小问题;
- 高阶函数:接收另一个函数作为参数,称为函数式编程;
- 函数式编程:
lambda 表达式;
用于函数式编程的函数:map、filter、reduce;
- 变量可指向函数:即函数本身也可赋值给变量(给函数取别名);
函数名也是变量,也可给函数名赋值,但将导致函数名不再指向该函数,不具有原功能;
>>> def add(x, y, f):
... return(f(x) + f(y))
>>> add(-5, 6, abs)
>>> list(map(str, range(0, 10)))
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> [str(i) for i in range(10)]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> def func(x):
... return x.isalnum()
>>> seq = ["foo", "x41", "?!", "***"]
>>> list(filter(func, seq))
['foo', 'x41']
>>> [x for x in seq if x.isalnum()]
['foo', 'x41']
>>> numbers = [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, numbers)