85 votes

Quand est-il préférable d'utiliser zip au lieu de izip ?

Quand est-il préférable d'utiliser zip au lieu de itertools.izip ?

0 votes

Une raison en faveur de zip trop évident, mais qui vaut quand même la peine d'être souligné, c'est que izip renvoie un iterator qui ne peut être parcouru qu'une seule fois, c'est-à-dire que dans ii = izip(a,b) ; f(ii) ; g(ii) ici une liste vide [] est transmis à g .

11 votes

Pour votre information, la version de Python 3 zip est la fonction de Python 2 izip . En général, Python 3 a modifié la plupart des fonctions pour utiliser des itérateurs, comme range, filter, les fonctions dict, etc

101voto

Don Points 5574

zip calcule toute la liste en une seule fois, izip ne calcule les éléments que sur demande.

Une différence importante est que 'zip' renvoie une liste réelle, 'izip' renvoie un 'objet izip', qui n'est pas une liste et ne supporte pas les fonctionnalités spécifiques aux listes (comme l'indexation) :

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

Ainsi, si vous avez besoin d'une liste (et non d'un objet ressemblant à une liste), utilisez simplement 'zip'.

En outre, "izip" peut être utile pour économiser de la mémoire ou des cycles.

Par exemple, le code suivant peut se terminer après quelques cycles, il n'est donc pas nécessaire de calculer tous les éléments de la liste combinée :

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

en utilisant zip aurait calculé tous (a, b) couples avant d'entrer dans le cycle.

En outre, si lst_a et lst_b sont très grandes (par exemple, des millions d'enregistrements), zip(a, b) va construire une troisième liste avec un double espace.

Mais si vous avez de petites listes, peut-être zip est plus rapide.

9 votes

Vous avez raison. J'ai commencé avec de bonnes intentions et puis je suis tombé dans des trucs théoriques...

44voto

Amber Points 159296

Lorsque vous savez que vous voudrez la liste complète des éléments construits (par exemple, pour la transmettre à une fonction qui modifierait cette liste en cours de route). Ou lorsque vous voulez forcer les arguments que vous passez à la fonction zip() pour être complètement évalué à ce moment précis.

1 votes

Ne serait-il pas préférable d'utiliser izip dans le premier cas car il est plus rapide puisqu'il réutilise le tuple et il n'y a pas de réelle raison de ne pas utiliser izip ?

1 votes

@user1815201 : izip ne fait que réutiliser le tuple si le tuple a été publié avant que l'itération suivante ne commence, donc il ne vous rapporte rien. Cela dit, toute perte est triviale aussi, donc je suis d'accord qu'il y a peu de raison de ne pas utiliser izip exclusivement, en enveloppant avec list si vous avez besoin d'un list ; vous pouvez en fait faire cela de la manière "correcte" en ajoutant from future_builtins import zip au code Py2, ce qui rend simple zip en izip (préparation de la transition vers Py3).

7voto

Sakib Ahammed Points 2283

La bibliothèque itertools fournit des "itérateurs" pour les fonctions Python courantes. D'après la documentation d'itertools, "Comme zip() sauf qu'il retourne un itérateur au lieu d'une liste". Le I dans izip() signifie "itérateur".

Les itérateurs Python sont une séquence "lazy loaded" qui permet d'économiser de la mémoire par rapport à une liste régulière en mémoire. Ainsi, vous utiliserez itertools.izip(a, b) lorsque les deux entrées a, b sont trop grandes pour être gardées en mémoire en une seule fois.

Recherchez les concepts Python liés au traitement séquentiel efficace :

"generators" & "yield"
"iterators"
"lazy loading"

0 votes

Bien expliqué.

5voto

Dans la version 2.x, lorsque vous besoin de une liste au lieu d'un itérateur.

0 votes

Pouvez-vous me donner un exemple où cela pourrait se produire ?

3 votes

Pas vraiment. C'est pourquoi j'ai tendance à préférer itertools.izip() sauf lorsque les gains seraient purement statistiques.

2 votes

Un cas où vous avez besoin d'une liste est celui où vous prévoyez d'accéder aux éléments du résultat par index ou avez besoin de trouver la longueur totale. lst = zip(lst_a, lst_b) permet à lst[1] ou len(lst) . Cependant, pour ilst = itertools.izip(lst_a, lst_n) vous échouerez en essayant de ilst[1] ou len(ilst) .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X