延迟绑定
需要注意的一点是,python函数的作用域是由代码决定的,也就是静态的,但它们的使用是动态的,是在执行时确定的。
>>> def foo(n):
return n * i
>>> fs = [foo for i in range(4)]
>>> print fs[0](1)
当你期待结果是0的时候,结果却是3。
这是因为只有在函数foo被执行的时候才会搜索变量i的值, 由于循环已结束, i指向最终值3, 所以都会得到相同的结果。
在闭包中也存在相同的问题:
def foo():
fs = []
for i in range(4):
fs.append(lambda x: x*i)
return fs
for f in foo():
print f(1)
返回:
3
3
3
3
解决方法,一个是为函数参数设置默认值:
>>> fs = [lambda x, i=i: x * i for i in range(4)]
>>> for f in fs:
print f(1)
另外就是使用闭包了:
>>> def foo(i):
return lambda x: x * i
>>> fs = [foo(i) for i in range(4)]
>>> for f in fs:
print f(1)
或者:
>>> for f in map(lambda i: lambda x: i*x, range(4)):
print f(1)
使用闭包就很类似于偏函数了,也可以使用偏函数:
>>> fs = [functools.partial(lambda x, i: x * i, i) for i in range(4)]
>>> for f in fs:
print f(1)
这样自由变量i都会优先绑定到闭包函数上。