为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

弑天下 2019-12-04 14:55:19
在python 2.6中:[x() for x in [lambda: m for m in [1,2,3]]]结果是:[3, 3, 3]我希望输出为[1、2、3]。即使使用非列表理解方法,我也会遇到完全相同的问题。甚至在我将m复制到另一个变量之后。我想念什么?
查看完整描述

3 回答

?
守候你守候我

TA贡献1802条经验 获得超10个赞

为了使Lambda记住的值m,可以使用具有默认值的参数:


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

# [1, 2, 3]

之所以可行,是因为默认值在定义时设置一次。现在,每个lambda都会使用自己的默认值,m而不是m在lambda执行时在外部范围中查找的值。


查看完整回答
反对 回复 2019-12-04
?
MM们

TA贡献1886条经验 获得超2个赞

您遇到的效果称为闭包,当您定义引用非局部变量的函数时,该函数将保留对变量的引用,而不是获取其自己的副本。为了说明这一点,我将把您的代码扩展为等效版本,而无需任何理解或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,并且所有三个函数都看到相同的值。


查看完整回答
反对 回复 2019-12-04
?
手掌心

TA贡献1942条经验 获得超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。


查看完整回答
反对 回复 2019-12-04
  • 3 回答
  • 0 关注
  • 509 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信