Самое простое решение заключается в создании списка:
words = list(words_generator(text))
Другим вариантом является использование itertools.tee
:
words, words_copy = itertools.tee(words_generator(text))
Впоследствии вы можете использовать обе копии итерации. Однако имейте в виду, что если вы сначала полностью перейдете к копированию, тогда будет проще и эффективнее использовать память для простого создания списка. Чтобы увидеть какой-либо коэффициент усиления памяти, вы должны как-то перебирать обе копии одновременно ». Например что-то вроде:
filtered = filter_generator(words)
total = 0
for word, _ in zip(filtered, words_copy): # use itertools.izip in python2
counter[word] += 1
total += 1
total += sum(1 for _ in words_copy)
который использует в большинстве O(n-k)
памяти, где n
это количество слов в тексте и k
этого числа интересных слов в тексте.Вы можете упростить код немного с помощью:
from itertools import zip_longest #izip_longest in python2
filtered = filter_generator(words)
total = 0
for word, _ in zip_longest(filtered, words_copy):
counter[word] += 1
total += 1
del counter[None]
который использует только O(1)
память (если генераторы постоянного пространства).
Обратите внимание, однако, что наличие явных циклов замедляет код, поэтому в конце, если память не является опцией, может быть лучшим решением для построения list
для words
.
Вы можете просто поместить код '_itercount' внутри' __iter__' (да, '__iter__' может быть генератором). – Bakuriu
Я не понимаю, почему вы сделали это повторным, поскольку счетчик не сбрасывается. Это означает, что он «сломан», если вы используете его в нескольких циклах, я думаю. Вы должны переместить 'self._count' из переменной класса в переменную на итераторе. – Veedrac
@Veedrac Кто сказал, что он повторим? Этот код в точности эквивалентен вашему. Единственное различие заключается в том, что он использует генератор, чтобы избежать определения '__next__' (и терпит неудачу в его назначении, так как он определяет другой бесполезный метод для этого, чего я не понимаю. Либо укажите' __iter__' + '__next__ 'или' __iter__' в качестве генератора.) – Bakuriu