2017-02-09 14 views
6

В python я попытался создать копию моего итератора с использованием назначения, однако он создает копию итератора, ссылающуюся на оригинальный итератор. Например:Как создать копию итератора python?

my_list = [5, 4, 3,2] 
first_it = iter(my_list) 
second_it = first_it 
print next(first_it)  #it will print 5 
print next(second_it)  #it will print 4 
print next(first_it)  #it will print 3 

Как вы видите в примере first_it и second_it оба относятся к одному итераторному объекту. Возможно ли создать копию объекта итератора, которая не относится к исходному объекту?

Примечание Этот вопрос о том, как создать копию объекта итератора по значению. Поэтому не обращайте внимание на решения for item in my_list:.
Заранее спасибо

ответ

9

Используйте itertools.tee() function для изготовления копий; они используют буфер для обмена результатами между различными итераторов:

from itertools import tee 

my_list = [5, 4, 3,2] 
first_it = iter(my_list) 
first_it, second_it = tee(first_it) 
print next(first_it) # prints 5 
print next(second_it) # prints 5 
print next(first_it) # prints 4 

Обратите внимание, что вы больше не должны использовать оригинальный итератор; используйте только тройники.

Обратите внимание, что буфер также означает, что они могут понести значительную стоимость памяти, если вы продвинете одну из копий далеко впереди других! Из документации:

Для этого может потребоваться значительное вспомогательное хранилище (в зависимости от того, сколько временных данных необходимо сохранить). В общем случае, если один итератор использует большинство или все данные перед запуском другого итератора, быстрее использовать list() вместо tee().

+0

Я попытался использовать 'copy.copy()' и он тоже работал. Может быть, есть скрытый улов? –

+2

@ Jean-FrançoisFabre: Это не сработает для генератора. Попробуйте с генератором, который использует 'while True: yield random.random()' например. –

+0

относящийся к: «вы не можете развести генератор», вероятно. –