今天我探索了Python的奇怪的行为。一个例子:
closures = []
for x in [1, 2, 3]:
# store `x' in a "new" local variable
var = x
# store a closure which returns the value of `var'
closures.append(lambda: var)
for c in closures:
print(c())
上面的代码打印
3
3
3
但我希望它打印
1
2
3
我自己解释这种行为,var
总是相同的局部变量(而python不像其他语言那样创建新的变量)。如何修复上面的代码,以便每个闭包都返回另一个值?
答案 0 :(得分:9)
最简单的方法是使用lambda的默认参数,这样x
的当前值被绑定为函数的默认参数,而不是var
被查找在每次通话的包含范围内:
closures = []
for x in [1, 2, 3]:
closures.append(lambda var=x: var)
for c in closures:
print(c())
或者你可以创建一个闭包(你所拥有的不是闭包,因为每个函数都是在全局范围内创建的):
make_closure = lambda var: lambda: var
closures = []
for x in [1, 2, 3]:
closures.append(make_closure(x))
for c in closures:
print(c())
make_closure()
也可以这样写,这可能使它更具可读性:
def make_closure(var):
return lambda: var
答案 1 :(得分:6)
您无法在循环内的本地范围内创建新变量。无论您选择什么名称,您的函数将始终是该名称的闭包并使用其最新值。
最简单的方法是使用关键字参数:
closures = []
for x in [1, 2, 3]:
closures.append(lambda var=x: var)
答案 2 :(得分:1)
在您的示例中,var
始终绑定到循环的最后一个值。您需要使用closures.append(lambda var=var: var)
将其绑定到lambda中。