Die for-in-Schleife in Python wird über das Iterationsprotokoll implementiert, das auf zwei speziellen Methoden basiert: __iter__() und __next__(). Wenn die Schleife beginnt, ruft Python iter(obj) auf (sucht nach der Methode __iter__). Wenn ein Iteratorobjekt zurückgegeben wird, das __next__() definiert, beginnt die Schleife, diese Methode aufzurufen, um jedes nächste Element zu erhalten.
Wenn das Element erfolgreich ausgegeben wird, wird die Iteration fortgesetzt. Wenn die Ausnahme StopIteration ausgelöst wird, wird die Schleife beendet.
Beispiel eines benutzerdefinierten Iterators:
class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 for num in Counter(1, 3): print(num) # Gibt 1, 2, 3 aus
Feinheit: Viele Standarddatenstrukturen in Python implementieren das Iteratorprotokoll; Sie können Ihre Objekte leicht ebenso machen.
Kann die for-in-Schleife mit jedem Python-Objekt verwendet werden? Was ist der Unterschied zwischen einem iterierbaren Objekt und einem Iterator?
Antwort: Nein, die for-in-Schleife erfordert, dass das Objekt iterierbar ist, d.h. die Methode __iter__() implementiert, die einen Iterator (ein Objekt mit der Methode __next__()) zurückgibt. Der Iterator gibt sich selbst über __iter__() zurück, das iterierbare Objekt jedoch nicht.
Beispiel:
lst = [1, 2, 3] iterator = iter(lst) print(hasattr(lst, '__iter__')) # True print(hasattr(iterator, '__next__')) # True (Iterator) print(hasattr(lst, '__next__')) # False (kein Iterator)
Geschichte
Projekt: Verarbeitung großer Dateien.
Problem: Im Projekt versuchten sie, den Durchlauf über ein Dateiobjekt (Iteration über die Zeilen einer Datei) zweimal zu wiederholen, ohne eine neue Datei explizit zu öffnen — und beim zweiten Durchlauf erhielten sie keine Zeile (der Zeiger war bereits am Ende der Datei!).
Geschichte
Projekt: Integration der eigenen Sammlungs-Klasse mit dem Framework.
Problem: Die Klasse implementierte nur
__getitem__, nicht jedoch__iter__, und war nicht kompatibel mit Generatoren und Standard-Schleifen (for). Dadurch funktionierten externe Bibliotheken nicht, die einen Iterator erwarteten.
Geschichte
Projekt: Verwendung von map/filter in benutzerdefinierten Sammlungen.
Problem: Die eigene Listenklasse implementierte nicht
__iter__und__next__, und war nicht kompatibel mit vielen Standardfunktionen von Python, was sich erst nach Integrationstests herausstellte und erhebliche Überarbeitungen erforderte.