I came across python behavior that is hard for me to understand. This is the code for the evidence concept:
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)]
The conclusion above:
['spam', 'spam', 'spam'] ['foo', 'bar', 'spam']
The behavior of loop_one surprising to me, since I expect it to behave like loop_two : el is an immutable value (string) that changes in each loop, but lambda seems to hold a pointer to a "cyclic variable" , for example, if the loop will process the same memory address for each element of the sequence.
The above behavior is the same with full-blown functions with a for loop in them (therefore, it is not the syntax for defining a list).
But wait: more ... and more mysterious!
The following script works like loop_one :
b = [] for foo in ("foo", "bar"): b.append(lambda: foo) print [a() for a in b]
(output: ['bar', 'bar'] )
But look what happens if you replace the variable name foo with a :
b = [] for a in ("foo", "bar"): b.append(lambda: a) print [a() for a in b]
(output: [<function <lambda> at 0x25cce60>, <function <lambda> at 0x25cced8>] )
Any idea what is going on here? I suspect there should be some information related to the underlying C implementation of my interpreter, but I have nothing (Jthon, PyPy or the like) to check if this behavior is compatible across different implementations.