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中的参数?的主要内容,如果未能解决你的问题,请参考以下文章

Python中的匿名函数——lambda函数

python中的lambda函数用法

Python:lambda表达式的两种应用场景

python编程_匿名函数_lambda

Python知识点

新手入门,深入解析 python lambda表达式