Print out what l and g are, without the comprehension. I’m guessing that it’s a list containing one string in the first case, and just the string in the second.
>>> l = [ (lambda: i) for i in (1, 2, 3) ]
>>> [ f() for f in l ]
[3, 3, 3]
>>> g = ( (lambda: i) for i in (1, 2, 3) )
>>> [ f() for f in g ]
[1, 2, 3]
You should’ve posted this snippet in the first place since it’s fundamentally different from the code in the OP.
[ (lambda: i) for i in (1, 2, 3) ] is a list comprehension that creates a list of functions returning i, which isn’t evaluated until [ f() for f in l ], at which time i is already 3.
( (lambda: i) for i in (1, 2, 3) ) is a generator expression that doesn’t output lambda: i until [ f() for f in g ] iterates over g, so lambda: i gets created and evaluated while i gets incremented.
Yes, I would have. This behavior may indeed be confusing to newcomers but would become a second nature once you understand the distinctions between a comprehension and a generator.
A generator expression shares a similar syntax with a comprehension, but is not at all a comprehension. It defines a generator that does not evaluate the expression within until its __next__ method is called.
IMHO, no difference : for any kind of iterable (lazy — generator — or not — list): for is in both cases calling next on the object it is iterating through.
No, the __next__ method I’m talking about is of the generator object that the generator expression creates, not the __next__ method of the object that is being iterated in the expression.
A generator expression is not a comprehension. Again, please read the documentation first.
Because imho a list comprension and a generator comprehension are expressing semantically (if you have no side effects) the same data structure, just delaying evaluation in the former case. They should return the same data.
I may be wrong, but this is the way I’m used to in order to optimize production code.
But whether or not evaluation is delayed is the crucial difference in the outcome because in the case of your list comprehension, the lambda functions are called only afteri has finished iterating through (1, 2, 3), ending up as 3, while in the case of your generator expression, the lambda functions are called whilei is iterating over (1, 2, 3).