Когда лучше использовать zip вместо izip?

Когда лучше использовать zip вместо itertools.izip?


person Neil G    schedule 14.02.2011    source источник
comment
Одна из причин в пользу zip , слишком очевидная, но все же заслуживающая внимания, заключается в том, что izip возвращает iterator, который можно пройти только один раз. то есть в ii = izip(a,b) ; f(ii) ; g(ii) здесь пустой список [] передается в g.   -  person Causality    schedule 06.07.2016
comment
К вашему сведению, функция zip в Python 3 — это функция izip в Python 2. В общем, Python 3 изменил большинство функций, чтобы использовать итераторы, такие как диапазон, фильтр, функции dict и т. д.   -  person Charles L.    schedule 13.10.2018


Ответы (4)


Когда вы знаете, что вам понадобится полный список элементов (например, для передачи в функцию, которая изменит этот список на месте). Или когда вы хотите, чтобы аргументы, которые вы передаете zip(), полностью оценивались в этот конкретный момент.

person Amber    schedule 14.02.2011
comment
Не лучше ли использовать izip в первом случае, поскольку он быстрее, поскольку он повторно использует кортеж, и нет реальной причины не использовать izip? - person user1815201; 19.11.2013
comment
@ user1815201: izip повторно использует tuple только в том случае, если tuple был выпущен до начала следующей итерации, поэтому он ничего вам не дает. Тем не менее, любая потеря также тривиальна, поэтому я согласен с тем, что нет особых причин не использовать исключительно izip, обертывая list, если вам нужен list; на самом деле вы можете сделать это правильно, добавив from future_builtins import zip в код Py2, который превращает простой zip в izip (подготовка к переходу Py3). - person ShadowRanger; 28.12.2015

zip вычисляет весь список сразу, izip вычисляет элементы только по запросу.

Одно важное отличие состоит в том, что 'zip' возвращает фактический список, а 'izip' возвращает 'izip-объект', который не является списком и не поддерживает специфические для списка функции (такие как индексирование):

>>> l1 = [1, 2, 3, 4, 5, 6]
>>> l2 = [2, 3, 4, 5, 6, 7]
>>> z = zip(l1, l2)
>>> iz = izip(l1, l2)
>>> isinstance(zip(l1, l2), list)
True
>>> isinstance(izip(l1, l2), list)
False
>>> z[::2] #Get odd places
[(1, 2), (3, 4), (5, 6)]
>>> iz[::2] #Same with izip
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'itertools.izip' object is unsubscriptable

Итак, если вам нужен список (не похожий на список объект), просто используйте 'zip'.

Кроме того, izip может быть полезен для экономии памяти или циклов.

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

lst_a = ... #list with very large number of items
lst_b = ... #list with very large number of items
#At each cycle, the next couple is provided
for a, b in izip(lst_a, lst_b):
    if a == b:
        break
print a

использование zip привело бы к вычислению всех (a, b) пар перед входом в цикл.

Более того, если lst_a и lst_b очень большие (например, миллионы записей), zip(a, b) создаст третий список с двойным пробелом.

Но если у вас небольшие списки, возможно, zip будет быстрее.

person Don    schedule 14.02.2011
comment
Ты прав. Я начал с добрых намерений, а потом впал в теоретические штучки... - person Don; 15.02.2011

Библиотека itertools предоставляет «итераторы» для общих функций Python. Из документации itertools: «Как zip(), за исключением того, что он возвращает итератор вместо списка». I в izip() означает «итератор».

Итераторы Python представляют собой «ленивую загрузку» последовательности, которая экономит память по сравнению с обычным списком в памяти. Таким образом, вы должны использовать itertools.izip(a, b), когда два входа a, b слишком велики, чтобы хранить их в памяти одновременно.

Посмотрите концепции Python, связанные с эффективной последовательной обработкой:

"generators" & "yield"
"iterators"
"lazy loading"
person Sakib Ahammed    schedule 15.04.2015
comment
Красиво объяснил. - person Rahul; 09.01.2017

В версии 2.x, когда вам нужен список вместо итератора.

person Ignacio Vazquez-Abrams    schedule 14.02.2011
comment
Можете ли вы привести пример, где это может произойти? - person Neil G; 14.02.2011
comment
Не совсем. Вот почему я предпочитаю itertools.izip(), за исключением тех случаев, когда прибыль будет чисто статистической. - person Ignacio Vazquez-Abrams; 14.02.2011
comment
Один случай, когда вам нужен список, — это когда вы планируете получить доступ к элементам результата по индексу или вам нужно найти общую длину. lst = zip(lst_a, lst_b) позволяет lst[1] или len(lst). Однако для ilst = itertools.izip(lst_a, lst_n) вам не удастся выполнить ilst[1] или len(ilst). - person Jan Vlcinsky; 22.08.2013