One of my friends asked me about this piece of code:
array = [1, 8, 15]
gen = (x for x in array if array.count(x) > 0)
array = [2, 8, 22]
print(list(gen))
The output:
[8]
Where did the other elements go?
A generator expression is an expression that returns a generator object. Basically, a generator function is a function that contains a yield statement and returns a generator object.
A Python generator is a function that produces a sequence of results. It works by maintaining its local state, so that the function can resume again exactly where it left off when called subsequent times. Thus, you can think of a generator as something like a powerful iterator.
Python provides a generator to create your own iterator function. A generator is a special type of function which does not return a single value, instead, it returns an iterator object with a sequence of values. In a generator function, a yield statement is used rather than a return statement.
You need to call next() or loop through the generator object to access the values produced by the generator expression. When there isn't the next value in the generator object, a StopIteration exception is thrown. A for loop can be used to iterate the generator object.
The answer is in the PEP of the generator expressions, in particular the session Early Binding vs Late biding:
After much discussion, it was decided that the first (outermost) for-expression should be evaluated immediately and that the remaining expressions be evaluated when the generator is executed.
So basically the array
in:
x for x in array
is evaluated using the original list [1, 8, 15]
(i.e. immediately), while the other one:
if array.count(x) > 0
is evaluated when the generator is executed using:
print(list(gen))
at which point array
refers to a new list [2, 8, 22]
This becomes more clear if you give each array a unique name instead of re-binding array
:
array1 = [1, 8, 15]
gen = (x for x in array1 if array2.count(x) > 0)
array2 = [2, 8, 22]
print(list(gen))
x for x in array1
is evaluated at creation of the generator, but if array2.count(x) > 0
is evaluated lazily, which is why you can already reference a yet undefined variable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With