1、返回多个值
函数可以返回多个值,其实是将它们作为一个元组:
return x,y其实返回的是(x,y)。
2、函数的默认参数
>>> def add_end(L=[]):
... L.append('END')
... return L
...
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
所以定义默认参数要牢记一点:默认参数必须指向不变对象:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
3、可变参数
如下定义:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
调用时可以提供0个或任意个数字作为参数:
calc(1,2)
calc()
nums = [1, 2, 3]
calc(*nums)
这样调用时将多个数字组装成一个元组,而如果参数本身是元组,调用时前面加*。
4、关键字参数
关键字参数在函数内部自动组装为一个dict。
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
调用时可以只输入必选参数:
>>> person('Michael', 30)
name: Michael age: 30 other: {}
也可以输入其他可变参数:
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
还可以将一个字典作为可变参数:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
5、命名关键字参数
如果要限制关键字参数的名字,可以使用命名关键字参数:
def person(name, age, *, city, job):
print(name, age, city, job)
注意:name、age是位置参数,*不是参数而是位置符号,city、job是命名关键字参数。
调用如下:
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
命名关键字参数必须传入参数名。
6、函数定义的例子
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
正常的调用:
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
神奇的调用:
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4) kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}
>>> f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
7、生成器yield
对于斐波拉契数列(Fibonacci):
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
可以这样打印出来:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
使用生成器:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return
使用next调用:
>>> fib(6)
<generator object fib at 0x7fe7ba7719b0>
>>> o=fib(6)
>>> next(o)
1
>>> next(o)
1
>>> next(o)
2
>>> next(o)
3
>>> next(o)
5
>>> next(o)
8
>>> next(o)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
正常的调用:
>>> o=fib(6)
>>> def p(o):
... while True:
... try:
... x=next(o)
... print(x)
... except StopIteration as e:
... print('StopIteration')
... break
...
>>> p(o)
1
1
2
3
5
8
StopIteration
8、返回函数
>>> def lazy_sum(*args):
... def sum():
... ax = 0
... for n in args:
... ax=ax+n
... return ax
... return sum
...
>>> f=lazy_sum(1,3,5,7,9)
>>> f
<function sum at 0x7fe7ba7867d0>
>>> f()
25
9、匿名函数lambda
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
10、装饰器
以输出日志为例:
不带参数的装饰器:
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
带参数的装饰器:
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@functools.wraps(func)语句的功能是使func.__name__的值保持不变。
11、偏函数
>>> def func(a,b):
... return a+b
...
>>> func('what\'s ','up')
"what's up"
>>> func(1,2)
3
>>> import functools
>>> func2=functools.partial(func,b='end')
>>> func2('it\'s ')
"it's end"