奇怪的行为:列表理解内的Lambda

在python 2.6中:


[x() for x in [lambda: m for m in [1,2,3]]]

结果是:


[3, 3, 3]

我希望输出为[1、2、3]。即使使用非列表理解方法,我也会遇到完全相同的问题。甚至在我将m复制到另一个变量之后。


我想念什么?


弑天下
浏览 510回答 3
3回答

守候你守候我

为了使Lambda记住的值m,可以使用具有默认值的参数:[x() for x in [lambda m=m: m for m in [1,2,3]]]# [1, 2, 3]之所以可行,是因为默认值在定义时设置一次。现在,每个lambda都会使用自己的默认值,m而不是m在lambda执行时在外部范围中查找的值。

MM们

您遇到的效果称为闭包,当您定义引用非局部变量的函数时,该函数将保留对变量的引用,而不是获取其自己的副本。为了说明这一点,我将把您的代码扩展为等效版本,而无需任何理解或lambda。inner_list = []for m in [1, 2, 3]:    def Lambda():         return m    inner_list.append(Lambda)因此,此时,它inner_list具有三个函数,并且每个函数在调用时将返回的值m。但是要注意的一点是m,即使m改变了,他们都看到了相同的东西,直到很久以后他们才看它。outer_list = []for x in inner_list:    outer_list.append(x())特别是,由于内部列表是在外部列表开始构建之前完全构建的,m因此已经达到其最后一个值3,并且所有三个函数都看到相同的值。

手掌心

长话短说,您不想这样做。更具体地说,您遇到的是操作顺序问题。您正在创建lambda全部返回的三个单独的m,但是没有一个立即被调用。然后,当您到达外部列表理解时,它们都被称为的残差值为m3,即内部列表理解的最后一个值。-评论->>> [lambda: m for m in range(3)][<function <lambda> at 0x021EA230>, <function <lambda> at 0x021EA1F0>, <function <lambda> at 0x021EA270>]那是三个单独的lambda。并且,作为进一步的证据:>>> [id(m) for m in [lambda: m for m in range(3)]][35563248, 35563184, 35563312]同样,三个单独的ID。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python