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]]?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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
Method 2
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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0