闭包是指在函数中定义子函数。比较经典的用法是让子函数访问父函数中的局部变量,或者作为返回值返回并延迟执行。
Python中也可以使用闭包,但子函数中使用的外部变量在执行时才求值。因此,如果外部变量在子函数定义和执行之间发生变化,则会影响到最后的执行结果,本人就在最近犯了这个编程错误。Stackoverflow也讲到这个问题,下面给出一个具体的例子。
def foo():
funcs = []
for i in xrange(4):
def test():
print i
funcs.append(test)
for func in funcs:
func()
上面的例子里,我们希望用一个循环构建多个子函数并延迟执行,原本以为可以输出0,1,2,3,但实际输出是3,3,3,3,原因是执行时i的值已经变为3。
一种解决方法是,在子函数里使用参数代替外部变量,同时把参数名字绑定到外部变量变化前的值,如下所示。
import functools
def foo():
funcs = []
for i in xrange(4):
def test(j):
print j
funcs.append(functools.partial(test, i))
for func in funcs:
func()
上面的例子里,我们利用functools模块构建一个新的函数调用原来的子函数,同时把子函数的参数名绑定到当时i绑定的对象。最后,得到预期的输出。



