Подтвердить что ты не робот

Глубокое копирование генератора в python

Я использую функцию генератора, скажем:

def foo():
    i=0
    while (i<10):
         i+=1
         yield i

Теперь мне нужно будет скопировать генератор после любого количества итераций, чтобы новая копия сохранила внутреннее состояние (в примере будет такое же "i" ), но теперь будет независимым от оригинала (т.е. итерация по копии не должна изменять оригинал).

Я пробовал использовать copy.deepcopy, но я получаю сообщение об ошибке:

 "TypeError: object.__new__(generator) is not safe, use generator.__new__()"   

Очевидно, я мог бы решить это, используя обычные функции со счетчиками, например. Но я действительно ищу решение с использованием генераторов.

4b9b3361

Ответ 1

Есть три случая, о которых я могу думать:

  • Генератор не имеет побочных эффектов, и вы просто хотите, чтобы вы могли пройти через результаты, которые вы уже захватили. Вместо генератора вы можете считать кешированный генератор. Вы можете совместно использовать генератор кэша, и если какой-либо клиент подходит к тому элементу, который еще не был, он будет продвигаться вперед. Это похоже на метод tee(), но функция tee в самом генераторе/кеше, вместо того, чтобы требовать от клиента этого.

  • Генератор имеет побочные эффекты, но не историю, и вы хотите, чтобы иметь возможность перезапуска в любом месте. Подумайте о том, как написать сопрограмму, где вы можете передать значение в любое время.

  • Генератор имеет побочные эффекты и историю, что означает, что состояние генератора в G (x) зависит от результатов G (x-1), и поэтому вы не можете просто передать x обратно в него начать где угодно. В этом случае, я думаю, вам нужно быть более конкретным о том, что вы пытаетесь сделать, поскольку результат зависит не только от генератора, но и от состояния других данных. Вероятно, в этом случае есть лучший способ сделать это.

Ответ 2

Комментарий для itertools.tee был моим первым предположением. Из-за предупреждения о том, что вы не должны продвигать оригинальный генератор больше после использования tee, я мог бы написать что-то вроде этого, чтобы открутить копию:

>>> from itertools import tee
>>>
>>> def foo():
...   i = 0
...   while i < 10:
...     i += 1
...     yield i
...
>>>
>>> it = foo()
>>> it.next()
1
>>> it, other = tee(it)
>>> it.next()
2
>>> other.next()
2