考虑以下代码
func_list = []
def foo(d):
print 'num', num
_num = num
return d['level'] > _num
def get_f(num):
_num = num
def bar(d):
print 'num', _num
return d['level'] > _num
return bar
for num in (30, 60):
level_func = foo
#level_func = get_f(num)
func_list.append(level_func)
d = {'level': 40}
for f in func_list:
print f(d)
当level_func是foo时,两次调用都会输出num=60,而level_func = get_f(num),才会输出期望的num=30, num=60。
原因是循环中level_func都绑定了同一个local变量num,而循环结束后,变量num的值为60,所以输出都是60。而get_f里面定义了_num=num,bar函数的_num是指向get_f里面所定义的_num,这是因为Python里def定义函数创造了一个新的variable scope;循环两次,get_f里形成闭包,保存了循环当时的值。
但每次都要定义一个辅助函数(上例的get_f)总觉得麻烦,如何解决?其实可以利用Python的一个“坑”。
代码:
level_func = lambda d, num=num: return d['level'] > num
原理就是利用Python函数默认参数是在定义时绑定。
具体的差别可以用过dis模块来打印函数的bytecode查看。