Was ist der Unterschied zwischen Iteratoren und Generatoren? Einige Beispiele für die Verwendung der beiden Fälle wären hilfreich.
Über Ihren ersten Code-Schnipsel, würde ich gerne wissen, was sonst arg 'Stream' als die Liste[] sein könnte?
Was ist der Unterschied zwischen Iteratoren und Generatoren? Einige Beispiele für die Verwendung der beiden Fälle wären hilfreich.
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
return
AnweisungAufrufen der evens
Methode (Generator) ist wie üblich
num = [...]
for n in evens(num):
do_smth(n)
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
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.
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"?
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.
@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) ;)
Es ist schwierig, die Frage ohne 2 andere Begriffe zu beantworten: iterable
y iterator protocol
.
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:
iterator
hat __next__
Methode, iterable
nicht.__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
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í ).
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:
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);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;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);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 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.