I have this generator that yields lists:
def gen():
state = [None]
for i in range(5):
state[0] = i
yield state
And here's the output, when I call it:
>>> list(gen())
[[4], [4], [4], [4], [4]]
Why are all the elements [4]
? Shouldn't it be [[0], [1], [2], [3], [4]]
?
Python generators are a simple way of creating iterators. All the work we mentioned above are automatically handled by generators in Python. Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).
To reset a generator object in Python, we can use the itertools. tee method. to call itertools. tee with generator y to get a 2nd version of the generator.
Key takeaways: motivation and uses behind generators Generators are memory efficient since they only require memory for the one value they yield. Generators are lazy: they only yield values when explicitly asked. You can feed the output of a generator to the input of another generator to form data pipelines.
Python Generator functions allow you to declare a function that behaves likes an iterator, allowing programmers to make an iterator in a fast, easy, and clean way. An iterator is an object that can be iterated or looped upon.
You are reusing the same list object. Your generator returns the one object over and over again, manipulating it as it goes, but any other references to it see those same changes:
>>> r = list(gen())
>>> r
[[4], [4], [4], [4], [4]]
>>> r[0] is r[1]
True
>>> r[0][0] = 42
>>> r
[[42], [42], [42], [42], [42]]
Yield a copy of the list or create a new fresh list object instead of manipulating one.
def gen_copy():
state = [None]
for i in range(5):
state[0] = i
yield state.copy() # <- copy
def gen_new():
for i in range(5):
state = [i] # <- new list object every iteration
yield state
You are yielding
the same list/object
so you always see the last values added to the list. You should yield a copy:
yield state.copy()
Or create the list inside the first loop:
for i in range(5):
state = [i]
It would be as easy to create a new list/object each time:
def gen():
for i in range(5):
state = [None]
state[0] = i
yield state
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