Python使用闭包捕获对原始变量的引用。这些
lambda对象保留对
i名称的引用,可以通过该引用访问值。这意味着
i变量在
f完成后将继续存在。
您可以
.__closure__在lambda对象的元组中内省此闭包;函数具有相同的属性:
>>> L[0].__closure__(<cell at 0x1077f8b78: int object at 0x107465880>,)>>> L[0].__closure__[0]<cell at 0x1077f8b78: int object at 0x107465880>>>> L[0].__closure__[0].cell_contents4
这也是列表中 所有 lambda 都
L引用value
4而不是0到4的原因。它们都引用 相同的 闭包:
>>> L[0].__closure__[0] is L[1].__closure__[0]True
闭包引用 变量
,而不是定义闭包时该变量的值。循环的
i最后一次设置为
4,因此在查找时,对于列表中的所有lambda,都会找到
ilambda闭包
4。
如果您希望lambda
i在循环期间引用value,请在关键字参数中捕获它:
def f(): L = [] for i in range(5): L.append(lambda x, i=i: i ** x) return L
现在
i是lambda的局部变量,而不是闭包。
或者,创建一个全新的范围来从中绘制闭合:
def create_lambda(i): return lambda x: i ** xdef f(): return [create_lambda(i) for i in range(5)]
现在
create_lambda()是一个新的作用域,它具有自己的本地
i供lambda闭包引用。然后,每个lambda都有自己的闭包:
>>> L[0].__closure__[0] is L[1].__closure__[0]False
闭包引用特定命名空间中的变量;每次您调用函数时,都会创建一个新的本地名称空间,因此每个闭包都
i在
create_lambda与的其他调用不同的单独名称空间中引用
create_lambda。



