Ich stolperte über ein Verhalten in Python, dass ich ein schweres Verständnis habe. Dies ist der Proof-of-Concept-Code:Weird Lambda Verhalten in Schleifen
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)]
Der Ausgang der oben ist:
['spam', 'spam', 'spam']
['foo', 'bar', 'spam']
Das Verhalten von loop_one
ist überraschend für mich, wie ich es erwarten würde, wie loop_two
verhalten: el
ist ein unveränderlicher Wert (ein String), der sich bei jeder Schleife ändert, aber lambda
scheint einen Zeiger auf die "Schleifenvariable" zu speichern, als würde die Schleife die gleiche Speicheradresse für jedes Element der Sequenz wiederverwenden.
Das obige Verhalten ist das gleiche mit ausgewachsenen Funktionen mit einer for-Schleife in ihnen (so ist es nicht eine Liste Verständnis Syntax).
Aber warten Sie: es gibt mehr ... und mehr rätselhaft!
Das folgende Skript funktioniert wie loop_one
:
b = []
for foo in ("foo", "bar"):
b.append(lambda: foo)
print [a() for a in b]
(Ausgabe: ['bar', 'bar']
)
Aber sehen, was passiert, wenn man die Variablennamen foo
mit a
ersetzen:
b = []
for a in ("foo", "bar"):
b.append(lambda: a)
print [a() for a in b]
(Ausgabe: [<function <lambda> at 0x25cce60>, <function <lambda> at 0x25cced8>]
)
Eine Idee von dem, was hier passiert? Ich vermute, dass es ein Problem mit der zugrundeliegenden C-Implementierung meines Interpreters geben muss, aber ich habe nichts anderes (Jthon, PyPy oder Ähnliches), um zu testen, ob dieses Verhalten in verschiedenen Implementierungen konsistent ist.