¿Cuándo es mejor usar zip en lugar de izip?

81

¿Cuándo es mejor usar en ziplugar de itertools.izip?

Neil G
fuente
Una razón a favor zip, demasiado obvia pero aún digna de ser señalada, es que los izipretornos y los iteratorcuales se pueden atravesar solo una vez. es decir ii = izip(a,b) ; f(ii) ; g(ii), en , aquí []se pasa una lista vacía g.
Causalidad
5
FYI, la zipfunción de Python 3 es la de Python 2 izip. En general, Python 3 cambió la mayoría de las funciones para usar iteradores, como rango, filtro, funciones de dictado, etc.
Charles L.

Respuestas:

44

Cuando sepa que querrá que se construya la lista completa de elementos (por ejemplo, para pasar a una función que modificaría esa lista en el lugar). O cuando quiere forzar que los argumentos a los que está pasando zip()sean evaluados por completo en ese punto específico.

Ámbar
fuente
1
¿No sería mejor usar izip en el primer caso ya que es más rápido ya que reutiliza la tupla y no hay ninguna razón real para no usar izip?
user1815201
1
@ user1815201: izipsolo reutiliza tuplesi tuplese lanzó antes de que comience la siguiente iteración, por lo que no le proporciona nada. Dicho esto, cualquier pérdida también es trivial, por lo que estoy de acuerdo en que hay pocas razones para no usarlo de forma izipexclusiva, terminando con listsi necesita un list; en realidad se puede hacer esto de la manera "correcta" mediante la adición from future_builtins import zipal código Py2, lo que deja claro zipen izip(la preparación para la transición AP3).
ShadowRanger
98

zipcalcula toda la lista a la vez, izipcalcula los elementos solo cuando se le solicita.

Una diferencia importante es que 'zip' devuelve una lista real, 'izip' devuelve un 'objeto izip', que no es una lista y no admite funciones específicas de la lista (como la indexación):

>>> 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

Entonces, si necesita una lista (y no un objeto similar a una lista), simplemente use 'zip'.

Aparte de esto, 'izip' puede ser útil para guardar memoria o ciclos.

Por ejemplo, el siguiente código puede salir después de algunos ciclos, por lo que no es necesario calcular todos los elementos de la lista combinada:

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

el uso ziphabría calculado todas las (a, b) parejas antes de ingresar al ciclo.

Además, si lst_ay lst_bson muy grandes (por ejemplo, millones de registros), se zip(a, b)creará una tercera lista con doble espacio.

Pero si tienes listas pequeñas, quizás zipsea ​​más rápido.

Don
fuente
9
Tienes razón. Empecé con buenas intenciones y luego caí en cosas teóricas ...
Don
5

En 2.x, cuando necesita una lista en lugar de un iterador.

Ignacio Vázquez-Abrams
fuente
¿Puede darme un ejemplo de dónde podría suceder eso?
Neil G
3
Realmente no. Es por eso que tiendo a preferir, itertools.izip()excepto donde las ganancias serían puramente estadísticas.
Ignacio Vazquez-Abrams
2
Un caso, cuando necesita una lista, es cuando planea acceder a elementos del resultado por índice o necesita encontrar la longitud total. lst = zip(lst_a, lst_b)permite lst[1]o len(lst). Sin embargo, ilst = itertools.izip(lst_a, lst_n)fallará al intentarlo ilst[1]o len(ilst).
Jan Vlcinsky
5

La biblioteca itertools proporciona "iteradores" para funciones comunes de Python. De los documentos de itertools, "Como zip () excepto que devuelve un iterador en lugar de una lista". La I en izip () significa "iterador".

Los iteradores de Python son una secuencia de "carga diferida" que ahorra memoria sobre la lista normal en memoria. Por lo tanto, usaría itertools.izip (a, b) cuando las dos entradas a, b sean demasiado grandes para guardarlas en la memoria al mismo tiempo.

Busque los conceptos de Python relacionados con el procesamiento secuencial eficiente:

"generators" & "yield"
"iterators"
"lazy loading"
Sakib Ahammed
fuente
Bien explicado.
Rahul