我偶然發現了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或類似的東西)來測試這種行爲在不同的實現中是否一致。