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

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

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

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

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

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

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

2 ответов


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

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

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

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


комментарии 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