2015-07-28 2 views
5

Вот мой генератор:Почему этот генератор питона возвращает одно и то же значение каждый раз?

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 

А вот выход, когда я называю его:

>>> 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]] 

Если я снова выполнить инструкцию, я получаю что-то другое, чем [2, 0] (из-за np.random вызова), но такое же значение во всех y.

ответ

4

Повторное использование одного и того же объекта списка. Ваш генератор возвращает один объект снова и снова, манипулировать им, как она идет, но любые другие ссылки на него увидеть те же изменения:

>>> 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]] 

ПРИНЕСТИ копию из списка или создайте новый свежий список объектов вместо того, чтобы манипулировать им.

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

Вы yielding тот же list/object, так что вы всегда видите последние значения, добавленные в список. Вы должны дать копию:

yield state[:] 

Или создать список внутри первого цикла:

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

Было бы так легко добавить в пустой список во внутреннем цикле, создавая новый список/объект каждый раз:

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 
Смежные вопросы