Повторное использование zip-итератора в python 3 [дубликат]

torayeff спросил: 28 апреля 2018 в 09:16 в: python

У этого вопроса уже есть ответ:

  • Why can't I iterate twice over the same data? 3 ответа
  • Performing len on list of a zip object clears zip [duplicate] 2 ответа

У меня есть объект zip:

L_RANGES = zip(range(10, 20), range(11, 21))

вызов L_RANGES в порядке:

print(type(L_RANGES))
for a, b in L_RANGES:
  print(a, b)

Выход:

<class 'zip'>
10 11
11 12
12 13
13 14
14 15
15 16
16 17
17 18
18 19
19 20

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

L_RANGES = list(zip(range(10, 20), range(11, 21)))

3 ответа

Есть решение
Ofer Sadan ответил: 28 апреля 2018 в 09:59

Если вы должны создавать генератор каждый раз, когда вы зацикливаете, это решит все, потому что вы можете повторно использовать это несколько раз. Для этого преобразуйте L_RANGES из простого генератора в генераторы lambda, но не забудьте "вызывать" его каждый раз с помощью ():

L_RANGES = lambda: zip(range(10, 20), range(11, 21))for a, b in L_RANGES():
  print(a, b)for a, b in L_RANGES():
  print(a, b)#works as many times as you want

По сравнению с другими ответами это не занимает память (что является недостатком преобразования в список) и не требует нескольких переменных для каждого цикла, используя tee), что делает этот способ более гибким (вы можете, если необходимо, итератировать 1000 раз, не создавая L_RANGES_1...L_RANGES_999):

for i in range(1000):
    for a, b in L_RANGES():
        print(a, b)
jpp ответил: 28 апреля 2018 в 10:10
Для произвольного числа переменных вы должны использовать словарь, а не многие именованные переменные. Но остальная часть вашего ответа имеет смысл.
Ofer Sadan ответил: 28 апреля 2018 в 10:23
Хорошая точка @jpp
Aran-Fey jpp ответил: 29 апреля 2018 в 07:40

Итератор, однажды исчерпанный, не может быть повторно использован. В Python 3.x, zip возвращает итератор. Одним из решений является использование itertools.tee для копирования итератора n .

Например, если установить n = 2, мы можем сделать следующее :

from itertools import teeL_RANGES_1, L_RANGES_2 = tee(zip(range(10, 20), range(11, 21)), 2)for item in L_RANGES_1:
    # do somethingfor item in L_RANGES_2:
    # do something else

Преобразование в list позволяет использовать произвольное количество раз, но не рекомендуется для больших итераций из-за издержек памяти.

Для большого количества копий вы можете использовать словарь. Например:

L_RANGES = dict(zip(range(1000), tee(zip(range(10, 20), range(11, 21)), 1000)))
zipa ответил: 28 апреля 2018 в 09:21

В Python 3.x zip() возвращается итератор, который исчерпан.

Простейший способ избежать этого:

L_RANGES = list(zip(range(10, 20), range(11, 21)))