Why does this python generator return the same value every time?

Here is my generator:

import numpy as np def fun(): state = [1, 2] for i in range(10): for j, var in enumerate(state): next_st = np.random.randint(0, 3) state[j] = next_st yield state 

And here is the conclusion when I call it:

 >>> g = fun(); y = [x for x in g]; y [[2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0]] 

If I execute the statement again, I get something other than [2, 0] (due to the call to np.random ), but the same value in all y .

+5
source share
2 answers

Reuse of the same list object. Your generator returns one object over and over, manipulating it as it arrives, but any other references to it see the same changes:

 >>> g = fun(); y = [x for x in g]; y [[2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1]] >>> y[0] is y[1] True >>> y[0][0] = 42 >>> y [[42, 1], [42, 1], [42, 1], [42, 1], [42, 1], [42, 1], [42, 1], [42, 1], [42, 1], [42, 1]] 

Assume a copy of the list, or create a new new list object instead of processing it.

 def fun(): state = [1, 2] for i in range(10): for j, var in enumerate(state): next_st = np.random.randint(0, 3) state[j] = next_st yield state[:] # copy def fun(): for i in range(10): state = [1, 2] # new list object each iteration for j, var in enumerate(state): next_st = np.random.randint(0, 3) state[j] = next_st yield state 
+4
source

You are yielding the same list/object so you always see the last values ​​added to the list. You must provide a copy of:

  yield state[:] 

Or create a list inside the first loop:

  for i in range(10): state = [1, 2] 

It would be easy to add to an empty list in the inner loop, each time creating a new list / object:

 def fun(): for i in range(10): state = [] for j in range(2): next_st = np.random.randint(0, 3) state.append(next_st) yield state 
+4
source

All Articles