fan*_*656 4 python closures list-comprehension
在列表理解中使用闭包时,我发现了这个:
xs = [1, 2, 3]
fs = [lambda: _ for _ in xs]
vs = [_() for _ in fs]
print vs # [<function <lambda> at 0x020324B0>, <function <lambda> at 0x020D6AB0>, <function <lambda> at 0x020D6AF0>]
print vs[0] # <function <lambda> at 0x020324B0>
print vs[0]() # <function <lambda> at 0x020D6AF0>
print vs[0]()() # <function <lambda> at 0x020D6AF0>
print vs[0]()()() # <function <lambda> at 0x020D6AF0>
Run Code Online (Sandbox Code Playgroud)
不应该vs包含ints而不是lambdas?
但是如果我们在两个列表推导中使用不同的名称,它将按预期工作:
xs = [1, 2, 3]
fs = [lambda: x for x in xs]
vs = [f() for f in fs]
Run Code Online (Sandbox Code Playgroud)
我在Python2.7.5和Python2.7.8中进行了测试,两者都给出了相同的结果.(Python3.4.1按预期工作)是否有解释或是一个错误?
有两件事情发生了:
关闭时间晚了; 当你调用lambda时,它将_从关闭的命名空间中获取.它不会取_你创建lambda对象时的值.
Python 2没有为列表推导使用单独的命名空间,Python 3也是如此.
因此,_从您执行列表推导的命名空间中获取,并且当您在vs列表推导中执行lambda时,_绑定到您尝试执行的lambda(作为循环目标),而不是最后一个值来自xs.
在Python 3中,它的工作原理是因为除了可以迭代到列表推导的原始输入之外,所有名称都使用了新的命名空间.有_住在列表理解的新范围,从而保持结合3.
通过在第二次尝试中为循环目标使用不同的名称,您不会屏蔽已_关闭的名称,_仍然绑定到3.
| 归档时间: |
|
| 查看次数: |
964 次 |
| 最近记录: |