我偶然发现了python中的行为,我很难理解。这证明了概念代码:循环中的奇怪lambda行为
from functools import partial
if __name__ == '__main__':
sequence = ['foo', 'bar', 'spam']
loop_one = lambda seq: [lambda: el for el in seq]
no_op = lambda x: x
loop_two = lambda seq: [partial(no_op, el) for el in seq]
for func in (loop_one, loop_two):
print [f() for f in func(sequence)]
上面的输出是:
['spam', 'spam', 'spam']
['foo', 'bar', 'spam']
的loop_one
的行为令我感到诧异,因为我希望它表现为loop_two
:el
是一个不可变的值(一个字符串),在每个循环中都会改变,但lambda
似乎存储了一个指向“循环变量”的指针,就像循环会为该序列的每个元素回收相同的内存地址一样。
上述行为与其中使用for循环的全功能函数相同(所以它不是列表理解语法)。
但等一等:还有更多...更令人费解!
以下脚本就像loop_one
:
b = []
for foo in ("foo", "bar"):
b.append(lambda: foo)
print [a() for a in b]
(输出:['bar', 'bar']
)
但看会发生什么,当一个与a
替代变量名foo
:
b = []
for a in ("foo", "bar"):
b.append(lambda: a)
print [a() for a in b]
(输出:[<function <lambda> at 0x25cce60>, <function <lambda> at 0x25cced8>]
)
想知道这里发生了什么吗?我怀疑必须与我的解释器的底层C实现有关,但我没有其他任何东西(Jthon,PyPy或类似的东西)来测试这种行为在不同的实现中是否一致。