1、可接受任意数量参数的函数
【问题】
你想构造一个可接受任意数量参数的函数
【就决方案】
为了能使一个函数接受任意数量的位置参数,可以使用一个 * 参数
def avg(first,*rest)
return (first + sum(rest)) / (1 + len(rest))
avg(1,2)
avg(1,2,3,4)
为了接受任意数量的关键字参数,使用一个以 ** 开头的参数。
def a(x,*args,y):
pass
def b(x, *args,y,**kwargs):
pass
2、只接受关键字参数的函数
【问题】
你希望函数的某些参数强制使用关键字参数传递
【解决方案】
将强制关键字参数放到某个*参数或者单个星后面就能达到这种效果
def recv(maxsize,*,block):
...
pass
recv(1024,True) #TypeError
recv(1024,block=True) #ok
利用这种技术,我们还能在接受任意多个位置参数的函数中指定关键字参数,比如:
def mininum(*values,clip=None):
m = min(values)
if clip is not None:
m = clip if clip > m else m
return m
mininum(1,5,2,-5,10) # returns -5
mininum(1,5,2,-5,10,clip=0) # returns 0
3、给函数参数增加元信息
【问题】
你写好一个函数,然后想为这个函数的参数增加一些额外信息,这样的话其他使用者就能清楚的知道这个函数应该怎么使用。
【解决方案】
使用函数参数注解是一个很好的办法,它能提示程序员应该怎样正确使用这个函数。例如,下面有一个被注解了的函数
def add(x:int, y:int) -> int:
return x + y
4、定义匿名或内联函数
【问题】
你想为 sort()操作创建一个很短的回调函数,但又不想用 def 去写一个单行函数,而是希望通过否个快捷方式以内联方式来创建这个函数
【解决方案】
当一个函数很简单,仅仅是计算一个表达式的值的时候,就可以使用 lambda 表达式来代替。
add = lambda x,y:x+y
add(2,3)
def add(x,y):
return x + y
上面这两种方式效果是一样的
5、匿名函数捕获变量值
【问题】
你用lambda定义一个匿名函数,并想在定义时捕获到某些变量的值
【解决方案】
我们先看看代码的效果
x = 10
a = lambda y:x + y
x = 20
b = lambda y:x + y
现在我问你,a(10)和b(10)返回什么结果?如果你认为是20和30,那你就错了 。
a(10)
30
b(10)
30
这次中的奥秘就在于 lambda表达式中 x 是一个自由变量,在运行时绑定值,而不是定义的时候绑定值,这跟函数的默认参数定义是不同的。因此在调用lambda时,x是执行时的值。
如果想让某个匿名函数在定义的时候就捕获到值,可以将那个参数值设定为默认参数,就像下面这样
x = 10
a = lambda y,x=x,x+y
x = 20
b = lambda y,x=x,x+y
a(10)
# 20
b(10)
# 30
通过一个循环或列表推导中创建一个lambda表达式列表,并期望函数在定义时就记住每次的迭代值。
funcs=[lambda x:x+n for n in range(5)]
for f in funcs:
print(f(0))
#4
#4
#4
#4
#4
funs=[lambda x,n=n:x+n for n in range(5)]
for f in funcs:
print(f(0))
#0
#1
#2
#3
#4
通过使用函数默认值形式参数,lambda函数在定义时就能绑定值。