Gen*_*cos 18 python lambda list-comprehension
在python 2.6中:
[x() for x in [lambda: m for m in [1,2,3]]]
Run Code Online (Sandbox Code Playgroud)
结果是:
[3, 3, 3]
Run Code Online (Sandbox Code Playgroud)
我希望输出为[1,2,3].即使使用非列表理解方法,我也会得到完全相同的问题.甚至在我将m复制到另一个变量之后.
我错过了什么?
unu*_*tbu 16
要使lambda记住值m,可以使用带有默认值的参数:
[x() for x in [lambda m=m: m for m in [1,2,3]]]
# [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为默认值在定义时设置一次.每个lambda现在使用自己的默认值,m而不是m在lambda执行时在外部作用域中查找值.
您遇到的效果称为闭包,当您定义一个引用非局部变量的函数时,该函数会保留对该变量的引用,而不是获取自己的副本.为了说明,我将您的代码扩展为没有理解或lambdas的等效版本.
inner_list = []
for m in [1, 2, 3]:
def Lambda():
return m
inner_list.append(Lambda)
Run Code Online (Sandbox Code Playgroud)
所以,在这一点上,它inner_list有三个函数,每个函数在被调用时都会返回值m.但突出的一点是,他们都看到了相同m,即使m正在改变,他们也不会看到它,直到稍后再打电话.
outer_list = []
for x in inner_list:
outer_list.append(x())
Run Code Online (Sandbox Code Playgroud)
特别是,由于内部列表完全在外部列表开始构建之前构建,m因此已经达到其最后一个值3,并且所有三个函数都看到相同的值.
长话短说,你不想这样做.更具体地说,您遇到的是操作顺序问题.你正在创建三个单独lambda的返回m,但没有一个立即被调用.然后,当你到达外部列表理解并且它们都被称为剩余值为m3时,内部列表理解的最后一个值.
- 征求意见 -
>>> [lambda: m for m in range(3)]
[<function <lambda> at 0x021EA230>, <function <lambda> at 0x021EA1F0>, <function <lambda> at 0x021EA270>]
Run Code Online (Sandbox Code Playgroud)
这是三个独立的lambdas.
并且,作为进一步的证据:
>>> [id(m) for m in [lambda: m for m in range(3)]]
[35563248, 35563184, 35563312]
Run Code Online (Sandbox Code Playgroud)
同样,三个独立的ID.
| 归档时间: |
|
| 查看次数: |
2071 次 |
| 最近记录: |