2011-02-14 11 views

Respuesta

33

Cuando sabe, querrá la lista completa de elementos construidos (por ejemplo, para pasar a una función que modificaría esa lista in situ). O cuando desee forzar los argumentos que está pasando al zip() para que sean evaluados completamente en ese punto específico.

+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 una razón real para no usar izip? – user1815201

+1

@ user1815201: 'izip' solo reutiliza' tuple' si la 'tuple' se lanzó antes de que comience la siguiente iteración, por lo que no gana nada. Dicho esto, cualquier pérdida es trivial también, así que estoy de acuerdo en que hay pocas razones para no usar 'izip' exclusivamente, envolviendo con' list' si necesitas una 'list'; en realidad puedes hacerlo de la manera "correcta" al agregar 'from future_builtins import zip' al código Py2, lo que hace que' zip' sea 'izip' (preparándote para la transición de Py3). – ShadowRanger

4

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

+0

¿Puede darme un ejemplo de lo que podría pasar? –

+3

No realmente. Por eso tiendo a preferir 'itertools.izip()' excepto donde las ganancias serían puramente estadísticas. –

+2

Un caso, cuando necesita una lista, es cuando planea acceder a los 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, para 'ilst = itertools.izip (lst_a, lst_n)' fallarás al intentar 'ilst [1] 'o' len (ilst) '. –

79

zip calcula toda la lista a la vez, izip calcula los elementos solo cuando se solicita.

Una diferencia importante es que 'zip' devuelve una lista real, 'IZIP' devuelve un 'objeto IZIP', que no es una lista y no es compatible con las características de lista específica (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 

Por lo tanto, si necesita una lista (no es un objeto similar a una lista), simplemente use 'zip'.

Aparte de esto, 'izip' puede ser útil para salvar la memoria o los ciclos.

E.g. el código siguiente puede salir después de algunos ciclos, lo que no hay necesidad de 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 

usando zip habría calculado todos(a, b) parejas antes de entrar en el ciclo.

Además, si lst_a y lst_b son muy grandes (por ejemplo, millones de registros), zip(a, b) creará una tercera lista con doble espacio.

Pero si tiene listas pequeñas, tal vez zip es más rápido.

+4

Gracias. Sin embargo, esto principalmente responde cuando es 'izip' mejor que' zip' ... –

+6

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

3

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

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

Busque los conceptos relacionados con Python eficiente procesamiento secuencial:

"generators" & "yield" 
"iterators" 
"lazy loading" 
+0

Bien explicado. –

Cuestiones relacionadas