6

今天我探索了 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 不会像其他语言那样创建一个新变量)。如何修复上述代码,以便每个闭包返回另一个值?

4

3 回答 3

11

最简单的方法是为您的 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
于 2012-07-06T16:50:00.813 回答
6

您不能在循环内的本地范围内创建新变量。无论您选择什么名称,您的函数将始终是该名称的闭包并使用其最新值。

最简单的方法是使用关键字参数:

closures = []
for x in [1, 2, 3]:
    closures.append(lambda var=x: var)
于 2012-07-06T16:49:01.157 回答
1

在您的示例中,var始终绑定到循环的最后一个值。您需要使用 将其绑定到 lambda 中closures.append(lambda var=var: var)

于 2012-07-06T16:51:51.353 回答