如何强制 Python 在循环内创建新变量/新范围? [复制]

Posted

技术标签:

【中文标题】如何强制 Python 在循环内创建新变量/新范围? [复制]【英文标题】:How can I force Python to create a new variable / new scope inside a loop? [duplicate] 【发布时间】:2012-07-07 03:48:40 【问题描述】:

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

【问题讨论】:

提示:什么在 Python 中引入了新的变量作用域? 刚刚看到***.com/questions/7546285/… 是一个重复的问题。我该如何关闭这个或者我应该删除它? @tampis:投票结束吧——版主最终会决定这个问题是合并还是删除。 实际上,我认为这甚至不会像您认为的那样。尝试在第一个循环之后添加del var @cha0site del var 给出异常lobal name 'var' is not defined 【参考方案1】:

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

解决这个问题的最简单方法是使用关键字参数:

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

【讨论】:

感谢您的编辑,现在可以 +1。【参考方案2】:

最简单的方法是为你的 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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于如何强制 Python 在循环内创建新变量/新范围? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在循环内声明一个新变量而不是错误?

如何在不默认创建新范围的情况下在 tensorflow 中重用变量范围?

如何使用'for'循环将新变量传递给python脚本

python如何在循环中,每次循环都创建一个新的类?

为日期范围内的观察创建虚拟变量

Python - 使用 +/- 振荡值迭代数据框并根据条件创建新列