Ein iterabler Prozess muss eine __iter__
-Methode oder eine __getitem__
-Methode implementieren :
Ein Objekt kann mit
for
iteriert werden, wenn es__iter__()
oder__getitem__()
implementiert.
Ein Iterator benötigt eine __iter__
-Methode (die self
zurückgibt) und eine __next__
-Methode (ich bin nicht 100% ig sicher über __next__
).
__iter__
Methode? Ja!
Dies ist auch im Datenmodell dokumentiert:
object.__iter__(self)
Diese Methode wird aufgerufen, wenn ein Iterator für einen Container erforderlich ist. Diese Methode sollte ein neues Iteratorobjekt zurückgeben, das über alle Objekte im Container iterieren kann. Für Zuordnungen sollte es über die Schlüssel des Containers iterieren.
Iterator-Objekte müssen diese Methode ebenfalls implementieren. Sie müssen sich selbst zurückgeben . Weitere Informationen zu Iterator-Objekten finden Sie unter Iterator-Typen.
(Betonung meiner)
Was Ihre zweite Frage betrifft:
Ja, weil es eine Methode __iter__
hat.
Neben der formalen Implementierung ist es einfach zu überprüfen, ob etwas iterierbar ist, indem einfach überprüft wird, ob iter()
darauf aufgerufen werden kann:
Ebenso ist es möglich, zu überprüfen, ob etwas ein Iterator ist, indem überprüft wird, ob iter()
aufgerufen hat, was sich selbst zurückgibt:
Aber benutze sie nicht im Entwicklungscode, diese sind nur für "Visualisierung". Meistens iterieren Sie einfach über etwas mit for ... in ...
oder wenn Sie einen Iterator benötigen, verwenden Sie iterator = iter(...)
und bearbeiten dann den Iterator, indem Sie next(iterator)
aufrufen, bis ein StopIteration
ausgegeben wird.
Ein Iterator ist iterierbar . Und ja, ein Iterator hat immer eine __iter__
-Methode.
Aufruf von iter
für einen Iterator, der den __iter__
Hook aufruft, wird zurückgegeben derselbe Iterator:
Ein klassisches Beispiel für Methodenverkettung .
Wie Sie sicherlich bemerkt haben, folgen die meisten Implementierungen des Iterator-Protokolls für benutzerdefinierte Klassen immer:
%Vor% Dies ist der Fall, wenn die Iteration nicht an einen anderen Iterator delegiert wird, zB über return iter(...)
.
Es wäre ziemlich kontraintuitiv für einen Iterator , das Iterator-Protokoll denkst du nicht? Die __iter__
Implementierung des Protokolls wird im Folgenden beschrieben:
%Vor%Geben Sie das Iteratorobjekt selbst zurück. Dies ist erforderlich, um beides zu ermöglichen Container und Iteratoren, die mit den Anweisungen
for
undin
verwendet werden.
[ Hervorhebung von mir ]
Dieses Verhalten ist erwartungsgemäß konsistent mit Iterator-Objekten, die von Builtins zurückgegeben werden:
%Vor%P.S .: Ich entschuldige mich dafür, dass ich wiederholt donnert habe; es sieht so aus, als ob es das Richtige ist. Aber es ist nicht !
Ein Iterator ist iterierbar.
Das ist dokumentiert und erklärt hier :
Iteratoren müssen eine
__iter__()
-Methode haben, die das Iterator-Objekt selbst zurückgibt, so dass jeder Iterator auch iterierbar ist
Ein iterables ist nicht notwendigerweise ein Iterator
Iteratoren müssen per Definition eine __next__
-Methode haben. Um ein einfaches Gegenbeispiel zu geben:
Ein String-Objekt ist ein iterabler, aber kein Iterator.
AKTUALISIERT:
Ich stehe korrigiert.
Alle Iteratoren haben __iter__
. Aber nicht alle Iterables sind Iteratoren.
Bei iterable hat entweder __iter__
oder __getitem__
.
Zum Beispiel ist das Folgende ein Iterable, das kein Iterator ist. Ich kann klar über "c" iterieren, aber es hat keine Methode __iter__
:
UPDATE 2:
Nur weil ein Objekt __iter__
hat, bedeutet das nicht, dass ein __next__
iterierbar ist. Im Falle von Generator-Iteratoren reicht __iter__
aus, um iterierbar zu sein. Zum Beispiel:
Tags und Links python methods python-3.x iterator iterable