Python用lambda函数封闭范围变量

Ale*_*Mal 5 python lambda for-loop list

我写了这个简单的代码:

def makelist():
  L = []
  for i in range(5):
    L.append(lambda x: i**x)
  return L
Run Code Online (Sandbox Code Playgroud)

好的,现在我打电话

mylist = makelist()
Run Code Online (Sandbox Code Playgroud)

因为在稍后调用嵌套函数时会查找封闭范围变量,所以它们都有效地记住了相同的值:因此,我希望找到循环变量在最后一次循环迭代中的值,但是当我检查我的列表时我懂了:

>>> mylist[0](0)
1
>>> mylist[0](1)
4
>>> mylist[0](2)
16
>>> 
Run Code Online (Sandbox Code Playgroud)

我很困惑,为什么我的代码没有保留最后一个 for 循环值?为什么我不必显式保留带有默认参数的封闭范围值,如下所示:

L.append(lambda x, i=i: i ** x)
Run Code Online (Sandbox Code Playgroud)

提前致谢

cor*_*ump 5

尽管随着i时间的推移取多个值,但实际上只有一个变量, i。的内容i在循环期间正在改变。但闭包捕获的是变量,而不是值。在调用 lambda 之前,不会对它进行任何计算。调用该函数时,您将访问 的当前值i,该值恰好是最后一个值。

\n\n

至于为什么i=i解决这个问题,例如The Hitchhiker's Guide to Python ( Common Gotchas ) 中对此进行了解释:

\n\n
\n

Python\xe2\x80\x99 的默认参数在定义函数时计算一次,而不是每次调用函数时(就像 Ruby 中那样)。这意味着,如果您使用可变的默认参数并对其进行变异,那么您也将在以后对该函数的所有调用中对该对象进行变异。

\n
\n\n

因此,您创建的闭包内发生的每个新绑定(并且碰巧被命名为i)都会在创建闭包时计算其默认值。因此,您拥有“正确”的值,可以在调用闭包时使用。

\n