lambda函数不关闭Python中的参数?
Posted
技术标签:
【中文标题】lambda函数不关闭Python中的参数?【英文标题】:lambda function don't closure the parameter in Python? 【发布时间】:2011-11-22 18:24:42 【问题描述】:代码多说:
from pprint import pprint
li = []
for i in range(5):
li.append(lambda : pprint(i))
for k in li:
k()
产量:
4 4 4 4 4为什么不
0 1 2 3 4??
谢谢。
附:如果我编写完整的装饰器,它会按预期工作:
from pprint import pprint
li = []
#for i in range(5):
#li.append(lambda : pprint(i))
def closure(i):
def _func():
pprint(i)
return _func
for i in range(5):
li.append(closure(i))
for k in li:
k()
【问题讨论】:
见this question和my answer to this question 您可以看到这是通过将原始循环移动到一个函数中来关闭变量,然后在for k in li:
行之前调用该函数,因此 i
在模块级范围。它仍然可以工作(并获得相同的结果,因为它关闭的是引用而不是值),这意味着名称已关闭。
谢谢大家。我认为***.com/questions/2295290/… 不仅说明了解决方案,还说明了原因。我认为我的问题与***.com/questions/2295290/… 重复
这能回答你的问题吗? What do (lambda) function closures capture?
【参考方案1】:
你需要做的:
lambda i=i: pprint(i)
而不是捕获i
的当前值
【讨论】:
【参考方案2】:它确实正确引用了i
,唯一的问题是,当您的列表被填充时,i
将在迭代结束时从序列中的最后一项分配值,这就是您看到的原因4
全部结束。
【讨论】:
【参考方案3】:如果您不想使用默认参数 - 如果不小心使用参数调用可能会引入错误 - 您可以使用嵌套 lambda:
from pprint import pprint
li = []
for i in range(5):
li.append((lambda x: lambda: pprint(x))(i))
for k in li:
k()
这是您的 closure
函数的匿名版本。
【讨论】:
【参考方案4】:lambda 函数在 i
变量上创建闭包。第一个for
循环完成后,i
的值是4
。
然后第二个for
循环开始,所有的 lambda 函数都被执行。然后它们每个都打印i
的当前值,即4
。
【讨论】:
【参考方案5】:答案:因为 lambda 中的代码正在使用您的全局变量 i
。
如果您删除参数i
,您的第二个变体将与第一个使用 lambda 的变体相同:
def closure():
代替
def closure(i):
即函数内的代码将使用全局变量i
。
【讨论】:
它与变量的作用域无关,而是关闭的是对值的引用而不是对值的引用。请参阅我对这个问题的评论——如果你将for i in range
循环移动到一个函数中,所以i
在全局范围内不存在,然后在for k in li
循环之前调用该函数,它会给出相同的答案。
>如果将 for i in range 循环移动到一个函数中,所以 i 在全局范围内不存在,然后在 for k in li 循环之前调用该函数,它会给出相同的答案... --- 即非本地?我就是这个意思。
它正在寻找变量i
。由于没有函数参数i
,它从外部范围获取变量i
。以上是关于lambda函数不关闭Python中的参数?的主要内容,如果未能解决你的问题,请参考以下文章