806 Stimmen

Unterschied zwischen Pythons Generatoren und Iteratoren

Was ist der Unterschied zwischen Iteratoren und Generatoren? Einige Beispiele für die Verwendung der beiden Fälle wären hilfreich.

17voto

Marwan Mostafa Punkte 313

Beispiele aus Ned Batchelder sehr empfehlenswert für Iteratoren und Generatoren

Eine Methode ohne Generatoren, die etwas mit geraden Zahlen machen

def evens(stream):
   them = []
   for n in stream:
      if n % 2 == 0:
         them.append(n)
   return them

während bei Verwendung eines Generators

def evens(stream):
    for n in stream:
        if n % 2 == 0:
            yield n
  • Wir brauchen keine Liste noch ein return Anweisung
  • Effizient für große/unendlich lange Ströme ... es läuft einfach und liefert den Wert

Aufrufen der evens Methode (Generator) ist wie üblich

num = [...]
for n in evens(num):
   do_smth(n)
  • Generator auch zum Brechen von Doppelschleifen verwendet

Iterator

Ein Buch mit vielen Seiten ist ein iterierbar Ein Lesezeichen ist ein Iterator

und dieses Lesezeichen hat nichts anderes zu tun als sich zu bewegen next

litr = iter([1,2,3])
next(litr) ## 1
next(litr) ## 2
next(litr) ## 3
next(litr) ## StopIteration  (Exception) as we got end of the iterator

Zur Verwendung von Generator ... benötigen wir eine Funktion

Zur Verwendung von Iterator ... benötigen wir next y iter

Wie schon gesagt wurde:

Eine Generator-Funktion gibt ein Iterator-Objekt zurück

Der gesamte Nutzen von Iterator:

Jeweils ein Element im Speicher speichern

1 Stimmen

Über Ihren ersten Code-Schnipsel, würde ich gerne wissen, was sonst arg 'Stream' als die Liste[] sein könnte?

15voto

Hibou57 Punkte 6352

Frühere Antworten haben diesen Zusatz nicht berücksichtigt: Ein Generator hat eine close Methode, während typische Iteratoren dies nicht tun. Die close Methode löst eine StopIteration Exception im Generator, die in einem Programm abgefangen werden kann finally Klausel in diesem Iterator, um eine Chance zu bekommen, einige Aufräumarbeiten durchzuführen. Diese Abstraktion macht es am brauchbarsten in den großen als einfache Iteratoren. Man kann einen Generator so schließen, wie man eine Datei schließen kann, ohne sich darum kümmern zu müssen, was sich darunter befindet.

Meine persönliche Antwort auf die erste Frage lautet jedoch: iteratable hat eine __iter__ Methode nur, typische Iteratoren haben eine __next__ Methode nur Generatoren, die sowohl eine __iter__ und eine __next__ und eine zusätzliche close .

Für die zweite Frage wäre meine persönliche Antwort: In einer öffentlichen Schnittstelle neige ich dazu, Generatoren zu bevorzugen, da sie belastbarer sind: die close Methode und eine größere Kompatibilität mit yield from . Lokal kann ich Iteratoren verwenden, aber nur, wenn es sich um eine flache und einfache Struktur handelt (Iteratoren lassen sich nicht leicht zusammensetzen) und wenn es Gründe für die Annahme gibt, dass die Sequenz eher kurz ist, insbesondere, wenn sie vor dem Erreichen des Endes abgebrochen werden kann. Ich neige dazu, Iteratoren als ein Primitivum auf niedriger Ebene zu betrachten, außer als Literale.

Für den Kontrollfluss sind Generatoren ein ebenso wichtiges Konzept wie Versprechen: beide sind abstrakt und zusammensetzbar.

0 Stimmen

Könnten Sie ein Beispiel nennen, um zu veranschaulichen, was Sie meinen, wenn Sie von Komposition sprechen? Können Sie auch erklären, was Sie meinen, wenn Sie von " typisch Iteratoren"?

2 Stimmen

Eine andere Antwort ( stackoverflow.com/a/28353158/1878788 ) besagt, dass "ein Iterator eine Iterable ist". Da eine Iterable eine __iter__ Methode, wie kann ein Iterator mit __next__ nur? Wenn es sich um Iterabilien handeln soll, würde ich erwarten, dass sie unbedingt über __iter__ auch.

2 Stimmen

@bli: AFAICS diese Antwort hier bezieht sich auf die Norm PEP234 Sie ist also richtig, während die andere Antwort sich auf eine Implementierung bezieht und daher fragwürdig ist. Die Norm verlangt nur eine __iter__ auf Iterables, um einen Iterator zurückzugeben, der nur eine next Methode ( __next__ in Python3). Bitte verwechseln Sie nicht die Standards (für die Typisierung von Enten) mit ihrer Implementierung (wie ein bestimmter Python-Interpreter sie implementiert). Das ist ein bisschen wie die Verwechslung zwischen Generatorfunktionen (Definition) und Generatorobjekten (Implementierung) ;)

14voto

jouell Punkte 2769

No-code 4 Zeilen Spickzettel:

A generator function is a function with yield in it.

A generator expression is like a list comprehension. It uses "()" vs "[]"

A generator object (often called 'a generator') is returned by both above.

A generator is also a subtype of iterator.

10voto

irudyak Punkte 1961

Es ist schwierig, die Frage ohne 2 andere Begriffe zu beantworten: iterable y iterator protocol .

  1. Was ist der Unterschied zwischen iterator y iterable ? Konzeptionell iterieren Sie über iterable mit Hilfe der entsprechenden iterator . Es gibt einige Unterschiede, die zur Unterscheidung beitragen können iterator y iterable in der Praxis:

    • Ein Unterschied besteht darin, dass iterator hat __next__ Methode, iterable nicht.
    • Ein weiterer Unterschied - beide enthalten __iter__ Methode. Im Falle von iterable gibt er den entsprechenden Iterator zurück. Im Falle von iterator gibt er sich selbst zurück. Dies kann helfen, zu unterscheiden iterator y iterable in der Praxis.

    x = [1, 2, 3] dir(x) [... iter ...] x_iter = iter(x) dir(x_iter) [... iter ... next ...] type(x_iter) list_iterator

  2. Was sind iterables en python ? list , string , range usw. Was sind iterators ? enumerate , zip , reversed usw. Wir können dies anhand des oben beschriebenen Ansatzes überprüfen. Das ist etwas verwirrend. Wahrscheinlich wäre es einfacher, wenn wir nur einen Typ hätten. Gibt es einen Unterschied zwischen range y zip ? Einer der Gründe, dies zu tun - range hat eine Menge zusätzlicher Funktionen - wir können sie indizieren oder prüfen, ob sie eine Zahl enthält usw. (siehe Details aquí ).

  3. Wie können wir eine iterator uns selbst? Theoretisch können wir Folgendes umsetzen Iterator Protocol (siehe aquí ). Wir müssen schreiben __next__ y __iter__ Methoden und erhöhen StopIteration Ausnahme und so weiter (siehe Alex Martellis Antwort für ein Beispiel und eine mögliche Motivation, siehe auch aquí ). In der Praxis verwenden wir jedoch Generatoren. Das scheint bei weitem die wichtigste Methode zu sein, um iterators en python .

Ich kann Ihnen noch ein paar weitere interessante Beispiele nennen, die eine etwas verwirrende Anwendung dieser Konzepte in der Praxis zeigen:

  • in keras wir haben tf.keras.preprocessing.image.ImageDataGenerator ; diese Klasse hat keine __next__ y __iter__ Methoden; es handelt sich also nicht um einen Iterator (oder Generator);
  • wenn Sie seine flow_from_dataframe() Methode erhalten Sie DataFrameIterator die über diese Methoden verfügt; aber sie implementiert nicht StopIteration (was bei eingebauten Iteratoren nicht üblich ist in python ); in der Dokumentation können wir lesen, dass "A DataFrameIterator die Tupel von (x, y) " - wieder eine verwirrende Verwendung der Terminologie;
  • haben wir auch Sequence Klasse in keras und das ist eine benutzerdefinierte Implementierung einer Generatorfunktionalität (normale Generatoren sind nicht für Multithreading geeignet), aber es implementiert nicht __next__ y __iter__ Es handelt sich vielmehr um einen Wrapper für Generatoren (er verwendet yield Anweisung);

9voto

piotr.gradzinski Punkte 572

Dieser Thread behandelt in vielen Details alle Unterschiede zwischen den beiden, aber ich wollte etwas über den konzeptionellen Unterschied zwischen den beiden hinzufügen:

[...] eine Iterator wie im GoF-Buch definiert ruft Elemente aus einer Sammlung ab , während ein Generator kann Gegenstände "aus dem Nichts" erzeugen . Deshalb ist der Generator der Fibonacci-Folge ein gängiges Beispiel: Eine unendliche Reihe von Zahlen kann nicht in einer Sammlung gespeichert werden.

Ramalho, Luciano. Fließendes Python (S. 415). O'Reilly Media. Kindle Edition.

Sicherlich deckt sie nicht alle Aspekte ab, aber ich denke, sie vermittelt einen guten Eindruck davon, wann man nützlich sein kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X