Wann ist es besser, zip anstelle von izip zu verwenden?

81

Wann ist es besser zu verwenden zipals itertools.izip?

Neil G.
quelle
Ein Grund dafür zip, zu offensichtlich und dennoch erwähnenswert, ist die izipRückgabe einer, iteratordie nur einmal durchlaufen werden kann. dh in ii = izip(a,b) ; f(ii) ; g(ii), hier wird eine leere Liste []übergeben g.
Kausalität
5
Zu Ihrer Information, die zipFunktion von Python 3 ist die von Python 2 izip. Im Allgemeinen hat Python 3 die meisten Funktionen geändert, um Iteratoren wie Bereich, Filter,
Charles L.

Antworten:

44

Wenn Sie wissen, dass die vollständige Liste der Elemente erstellt werden soll (z. B. zum Übergeben an eine Funktion, die diese Liste an Ort und Stelle ändert). Oder wenn Sie erzwingen möchten, dass die Argumente, an die Sie übergeben, zip()an diesem bestimmten Punkt vollständig ausgewertet werden.

Bernstein
quelle
1
Wäre es nicht besser, izip im ersten Fall zu verwenden, da es schneller ist, da es das Tupel wiederverwendet und es keinen wirklichen Grund gibt, izip nicht zu verwenden?
user1815201
1
@ user1815201: izipVerwendet das nur wieder, tuplewenn das tuplevor Beginn der nächsten Iteration freigegeben wurde, sodass Sie nichts gewinnen. Das heißt, jeder Verlust ist auch trivial, daher stimme ich zu, dass es wenig Grund gibt, nicht izipausschließlich zu verwenden , listwenn Sie einen benötigen list. Sie können dies tatsächlich tun , um die „richtige“ Art und Weise durch Zugabe from future_builtins import zipzu Py2 - Code, die Ebene macht zipin izip(für PY3 Übergang Vorbereitung).
ShadowRanger
98

zipberechnet die gesamte Liste auf einmal, izipberechnet die Elemente nur auf Anfrage.

Ein wichtiger Unterschied besteht darin, dass 'zip' eine tatsächliche Liste zurückgibt, 'izip' ein 'izip-Objekt' zurückgibt, das keine Liste ist und keine listenspezifischen Funktionen (wie die Indizierung) unterstützt:

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

Wenn Sie also eine Liste benötigen (ein nicht listähnliches Objekt), verwenden Sie einfach 'zip'.

Abgesehen davon kann 'izip' nützlich sein, um Speicher oder Zyklen zu sparen.

Beispielsweise kann der folgende Code nach wenigen Zyklen beendet werden, sodass nicht alle Elemente der kombinierten Liste berechnet werden müssen:

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

using ziphätte alle (a, b) Paare vor dem Eintritt in den Zyklus berechnet .

Wenn darüber hinaus lst_aund lst_bsind sehr groß (zB Millionen von Datensätzen), zip(a, b)bauen eine dritte Liste mit Doppelraum.

Aber wenn Sie kleine Listen haben, ist vielleicht zipschneller.

Don
quelle
9
Du hast recht. Ich begann mit guten Absichten und fiel dann in theoretische Dinge ...
Don
5

In 2.x, wenn Sie eine Liste anstelle eines Iterators benötigen .

Ignacio Vazquez-Abrams
quelle
Können Sie mir ein Beispiel geben, wo das passieren könnte?
Neil G
3
Nicht wirklich. Aus diesem Grund bevorzuge ich eher, itertools.izip()wenn die Gewinne rein statistisch sind.
Ignacio Vazquez-Abrams
2
Ein Fall, wenn Sie eine Liste benötigen, ist, wenn Sie planen, auf Elemente des Ergebnisses über den Index zuzugreifen, oder die Gesamtlänge ermitteln müssen. lst = zip(lst_a, lst_b)erlaubt lst[1]oder len(lst). Doch für die ilst = itertools.izip(lst_a, lst_n)versuchen , werden Sie scheitern ilst[1]oder len(ilst).
Jan Vlcinsky
5

Die itertools-Bibliothek bietet "Iteratoren" für allgemeine Python-Funktionen. In den itertools-Dokumenten heißt es: "Wie zip (), außer dass ein Iterator anstelle einer Liste zurückgegeben wird." Das I in izip () bedeutet "Iterator".

Python-Iteratoren sind eine "faul geladene" Sequenz, die Speicher über die reguläre In-Memory-Liste spart. Sie würden also itertools.izip (a, b) verwenden, wenn die beiden Eingänge a, b zu groß sind, um gleichzeitig im Speicher zu bleiben.

Schlagen Sie die Python-Konzepte für eine effiziente sequentielle Verarbeitung nach:

"generators" & "yield"
"iterators"
"lazy loading"
Sakib Ahammed
quelle
Schön erklärt.
Rahul