This is because the following is simply
not a closure in Python:
lambdas = [(lambda: i) for i in xrange(10)]
This works, because it is a proper closure:
def build_closure(i):
return (lambda: i)
lambdas = [build_closure(i) for i in range(10)]
print("%s" % [f() for f in lambdas])
See
http://stackoverflow.com/questions/233673/lexical-closures-i...You can write something close only with lambda this way:
lambdas = [(lambda j=i: j) for i in range(10)]
The behavior is actually consistent between generators and list comprehensions, but it's giving the same result as a closure because generators are lazily evaluated (so f() is evaluated right on time, but i is still
not enclosed), and work only once: running it twice will have the generator exhausted:
In [12]: lambdas_gen = ((lambda: i) for i in xrange(10))
In [13]: [f() for f in lambdas_gen]
Out[13]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [14]: [f() for f in lambdas_gen]
Out[14]: []
That's why forcing the generation with list() causes evaluation of the generator, and only then do you evaluate the f()s, hence the same result as the list comprehension case.
Again, changing it to the following properly encloses i:
lambdas_genlist = list((lambda j=i: j) for i in range(10))