Die Sprache um Iteratoren und iterables ist ein wenig verwirrend. Die Hauptverwirrung kommt von dem Begriff "iterierbar", der eine Obermenge von "Iterator" sein kann oder nicht, abhängig davon, wie er verwendet wird.
Hier ist, wie ich die Dinge kategorisieren würde:
Ein iterable ist jedes Objekt, das auf durchlaufen werden können. Das heißt, es hat eine __iter__()
Methode, die einen Iterator zurückgibt, oder sie ist mit Ganzzahlen indexierbar (die eine Ausnahme von IndexError
auslöst, wenn sie außerhalb des Bereichs liegen), wodurch Python automatisch einen Iterator dafür erstellen kann. Dies ist eine sehr breite Kategorie. Ein Iterator ist ein Objekt, das dem Iteratorprotokoll folgt. Es hat eine __next__()
Methode (buchstabiert next
in Python 2), die das nächste Element ergibt, oder löst StopIteration
Ausnahme aus, wenn keine weiteren Werte verfügbar sind. Ein Iterator muss auch eine __iter__()
-Methode haben, die sich selbst zurückgibt, so dass alle Iteratoren auch iterierbar sind (da sie der oben angegebenen Definition von "iterable" entsprechen).
A nicht-Iterator iterable ist jede iterable die nicht ein Iterator ist. Dies ist oft das, was Menschen meinen, wenn sie den Begriff "iterierbar" im Gegensatz zu "Iterator" verwenden. Ein besserer Begriff in vielen Kontexten könnte "Sequenz" sein, aber das ist ein bisschen spezifischer (einige Nicht-Sequenz-Objekte sind Nicht-Iterator-Iterables, wie Wörterbücher, die eine Iteration über ihre Schlüssel erlauben). Das wichtige Merkmal dieser Kategorie von Objekten ist, dass Sie sie mehrmals durchlaufen können und die Iteratoren unabhängig voneinander arbeiten.
So zu versuchen, spezifische Fragen zu beantworten:
Es gibt selten einen guten Grund für jede Funktion speziell einen Iterator zu verlangen. Funktionen können normalerweise so ausgeführt werden, dass sie mit jeder Art von iterierbarem Argument funktionieren, entweder durch Aufruf von iter()
im Argument, um einen Iterator zu erhalten, oder durch Verwendung einer for
-Schleife, die den Iterator hinter den Kulissen erzeugt.
Das Gegenteil ist anders. Wenn eine Funktion einen iterierbaren Nicht-Iterator erfordert, muss das Argument möglicherweise mehrmals durchlaufen werden, sodass ein Iterator nicht ordnungsgemäß funktioniert. Funktionen in der Python-Standardbibliothek (und Built-Ins) haben jedoch selten eine solche Einschränkung. Wenn sie mehrere Male in einem iterierbaren Argument durchlaufen müssen, werden sie oft am Anfang in einen Sequenztyp (z. B. eine Liste) abgelegt, wenn es sich nicht bereits um eine Sequenz handelt.
Viele Funktionen geben Iteratoren zurück. Alle Generatorobjekte sind beispielsweise Iteratoren (sowohl diejenigen, die von Generatorfunktionen zurückgegeben werden, als auch solche, die mit Generatorausdrücken erzeugt werden). Dateiobjekte sind auch Iteratoren (obwohl sie das Iteratorprotokoll ein wenig verletzen, da Sie sie nach ihrer Erschöpfung mit ihrer seek()
-Methode neu starten können). Und alle Funktionen und Typen im Modul itertools
geben Iteratoren zurück, aber auch einige Builtins wie map()
(in Python 3). Die next()
Funktion ist in der Tat ungewöhnlich, da speziell ein Iterator benötigt wird. Dies liegt daran, dass es als Teil des Iterationsprotokolls selbst definiert ist. Es entspricht genau dem Aufruf der __next__()
Methode auf dem Iterator, einfach besser zum Lesen. Es hat auch eine Zwei-Argument-Form, die die StopIteration
Ausnahme unterdrückt, die andernfalls ausgelöst würde, wenn der Iterator erschöpft ist (es gibt stattdessen das Argument default
zurück).
Vielen Dank für die gründliche Erklärung. Nur um zu klären, list/tuple/range sind Sequenztyp. Nicht ein regulärer iterabler, sondern ein iterabler Nicht-Iterator. 'next (..' nimmt Iterator, der auch ein iterable ist. Aber es unterscheidet sich von einem anderen Typ von iterable (non-iterator iterable) = Sequenz = Liste/Tupel/Bereich. (Die spezifischen Details der anderen Unterschiede sind in Ihren Kommentaren) Es gibt mehr von ihnen, iterable, mit einer Verallgemeinerung: __iter __()? – theMobDog
Ja, ich denke du hast es. Iterable ist der allgemeinste Begriff. Einige iterables sind Iteratoren, andere nicht. Ich nenne diejenigen, die sind nicht "non-iterator iterables", aber viele Leute nennen sie einfach "iterables", was zu Verwirrung führt (da es nicht klar ist, ob sie den allgemeineren Begriff oder die spezifischere Nicht-Iterator-Unterkategorie bedeuten). – Blckknght