如何强制Python在循环中创建新的变量/新范围?

Ste*_*lla 3 python variables parameters closures for-loop

今天我探讨了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())
Run Code Online (Sandbox Code Playgroud)

上面的代码打印出来

3
3
3
Run Code Online (Sandbox Code Playgroud)

但是我希望它能打印出来

1
2
3
Run Code Online (Sandbox Code Playgroud)

我为自己解释了这种行为,var它始终是相同的局部变量(并且python不像其他语言那样创建新的行为).如何修复上面的代码,以便每个闭包都返回另一个值?

And*_*ark 9

最简单的方法是使用lambda的默认参数,这样当前值x被绑定为函数的默认参数,而不是var在每次调用的包含范围中查找:

closures = []
for x in [1, 2, 3]:
    closures.append(lambda var=x: var)

for c in closures:
    print(c())
Run Code Online (Sandbox Code Playgroud)

或者你可以创建一个闭包(你所拥有的不是闭包,因为每个函数都是在全局范围内创建的):

make_closure = lambda var: lambda: var
closures = []
for x in [1, 2, 3]:
    closures.append(make_closure(x))

for c in closures:
    print(c())
Run Code Online (Sandbox Code Playgroud)

make_closure() 也可以像这样写,这可能使它更具可读性:

def make_closure(var):
    return lambda: var
Run Code Online (Sandbox Code Playgroud)


Sve*_*ach 6

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

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

closures = []
for x in [1, 2, 3]:
    closures.append(lambda var=x: var)
Run Code Online (Sandbox Code Playgroud)