Python Iterators sind Python Objekte mit einer zählbaren Menge an Elementen, die das Iterator-Protokoll bestehend aus den beiden Funk­tio­nen __iter__() und __next__() im­ple­men­tie­ren.

Was genau sind Python Iterators?

Bei Python Iterators handelt es sich in erster Linie um eine spezielle Form von Python-Objekten. Sie zeichnen sich dadurch aus, dass sie aus einer Menge von zählbaren Elementen bestehen. Somit können Sie die Elemente aus einem Iterator zählen und über alle Elemente eines Python Iterators iterieren.

Tipp

Python ist eine her­vor­ra­gen­de Pro­gram­mier­spra­che für Web­pro­jek­te. Bei Ihrem Web­pro­jekt un­ter­stützt Deploy Now Sie durch au­to­ma­ti­sches De­ploy­ment und Building via GitHub, sodass Sie jederzeit den vollen Überblick behalten.

Iterators vs. Iterables

Python Iterators sind nicht zu ver­wech­seln mit Python Iterables. Al­ler­dings stehen der Iterator und das Iterable im engen Bezug zu­ein­an­der. Die ver­schie­de­nen Iterables wie die Python List zeichnen sich dadurch aus, dass sie eine __iter__()-Methode besitzen und somit das Iterieren durch sie er­mög­li­chen. Als Faust­re­gel können Sie sich merken: Alles, was beim Aufruf einer for-Loop auf der rechten Seite des Schlei­fen­kop­fes steht, ist ein Iterable.

l = [1, 2, 3]
for x in l:
	print(x)

Wie Sie sehen, taucht die Liste, die in der Variable „l“ hin­ter­legt ist, im Aufruf der Python-for-Schleife auf der rechten Seite des Schlei­fen­kop­fes hinter dem Schlüs­sel­wort „in“ auf und ist somit ein Iterable.

Aus einem Iterable können Sie einen Python Iterator ableiten. Um sich das zu ver­deut­li­chen und die Un­ter­schie­de zu verstehen, hilft ein Code­bei­spiel:

string = "test"
iteratorobjekt = iter(string)
next(iteratorobjekt)
iter(iteratorobjekt)

Zunächst wird im Code ein Python String mit dem Wert „test“ in der Variable namens „string“ hin­ter­legt. Strings fallen ebenfalls in die Kategorie der Iterables, denn Sie können durch jeden Buch­sta­ben der Zei­chen­ket­te iterieren.

Dass Sie durch Strings iterieren können, heißt im Grunde nichts anderes, als dass ein String ebenfalls die __iter__()-Funktion un­ter­stützt. Das sehen Sie auch in der nächsten Codezeile, in der wir einen Python Iterator dadurch erstellen, dass wir die iter-Funktion zusammen mit dem zuvor er­stell­ten String aufrufen. Diese gibt einen Pointer auf den Strings zurück und speichert ihn in der Variable namens „itera­tor­ob­jekt“. Der Python Iterator befindet sich also in einem Zustand. Diesen Zustand können wir verändern, indem wir die __next__()-Methode auf dem Python Iterator aufrufen. Sie sorgt dafür, den Pointer um ein Zeichen zu ver­schie­ben, sodass „itera­tor­ob­jekt“ nach dem Funk­ti­ons­auf­ruf auf den ersten Buch­sta­ben der Zei­chen­ket­te zeigt.

Der Funk­ti­ons­auf­ruf von __iter__(), der den Python Iterator als Über­ga­be­pa­ra­me­ter ent­ge­gen­nimmt, liefert eine Referenz auf eben­die­sen zurück. Python Iterators sind also selbst-ite­rier­bar.

Iterators vs. Ge­ne­ra­tors

Wichtig ist es auch, Iterators von Python Ge­ne­ra­tors zu un­ter­schei­den. Zwar ist jeder Generator in Python auch ein Iterator, umgekehrt gilt das aber nicht. Denn im Gegensatz zu einem Generator wird ein Iterator nicht zwingend mit einer Funktion gebildet, die einen yield-Ausdruck enthält.

Wofür und warum werden Python Iterators genutzt?

Das Haupt­ein­satz­ge­biet von Iterators ist natürlich das Iterieren selbst. Der große Vorteil von Iterators in Python ist es, dass sie nach dem Prinzip „Lazy Eva­lua­ti­on“ funk­tio­nie­ren. Anders gesagt bedeutet dies, dass jedes Element aus einem Python Iterator einzeln be­ar­bei­tet werden kann, ohne dass die Da­ten­struk­tur in Gänze in den Speicher geladen werden muss. Ein Ef­fi­zi­enz­vor­teil ist dieses Verhalten vor allem bei großen Da­ten­men­gen, bei denen so zu jeder Zeit nur ein Element geladen werden muss.

So erstellen Sie Python Iterators

Einen eigenen Python Iterator zu erstellen, ist nicht schwierig. Sie müssen hierzu einem Python-Objekt lediglich die __iter__()- und die __next__()-Funktion hin­zu­fü­gen. So können Sie ganz einfach einen Iterator erstellen, der alle geraden Zahlen zu­rück­gibt. Das Code­bei­spiel zeigt, wie das genau funk­tio­niert:

class geradeZahlen:
	def __iter__(self):
		self.x = 0
		return self
	def __next__(self):
		a = self.x
		self.x += 2
		return a
testobjekt = geradeZahlen()
testiterator = iter(testobjekt)
print(next(testiterator))
print(next(testiterator))
print(next(testiterator))
print(next(testiterator))

Um einen Python Iterator zu ver­wirk­li­chen, wird zunächst eine Klasse erstellt, die hier den Namen „ge­ra­de­Zah­len“ trägt. Innerhalb der Klasse werden die beiden Funk­tio­nen __iter__() und __next__() jeweils mit dem ge­wünsch­ten Verhalten im­ple­men­tiert.

Die Funktion __iter__() gibt in unserem Falle einfach nur eine Referenz auf den Iterator zurück, der die Zah­len­fol­ge der ganzen Zahlen beginnend bei der 0 be­her­ber­gen soll. Die Logik der Iteration, also dass nur jede zweite und somit jede gerade Zahl aus­ge­ge­ben wird, befindet sich innerhalb der __next__()-Funktion.

Nachdem die Klasse definiert wurde, wird ein Objekt der Klasse erstellt und in der Variablen namens „test­ob­jekt“ hin­ter­legt. Zu einem Python Iterator wird das Objekt durch den Aufruf der iter()-Funktion, wie wir im vor­he­ri­gen Code­bei­spiel schon gezeigt haben. An­schlie­ßend folgen vier Aufrufe von next(), deren Er­geb­nis­se auf dem Bild­schirm aus­ge­ge­ben werden. Der Output des obigen Code­ab­schnitts sieht wie folgt aus:

0
2
4
6

Python Iterators begrenzen

Der Iterator, der über die geraden Zahlen iteriert, würde ohne eine Be­gren­zung genau wie die Menge der geraden Zahlen ins Un­end­li­che laufen. Dies kann durch ein „Sto­pI­te­ra­ti­on“-Statement in Ver­bin­dung mit einem if-else-Statement in Python ver­hin­dert werden. Möchten Sie in Ihrem Python Iterator bei­spiels­wei­se alle geraden Zahlen bis ein­schließ­lich der 100 ausgeben, müssen Sie das obige Code­bei­spiel wie folgt anpassen:

class geradeZahlen:
	def __iter__(self):
		self.x = 0
		return self
	def __next__(self):
		if self.x <= 100:
			a = self.x
			self.x += 2
			return a	
		else:
			StopIteration
testobjekt = geradeZahlen()
testiterator = iter(testobjekt)
print(next(testiterator))
print(next(testiterator))
print(next(testiterator))
print(next(testiterator))

Im Code hat sich außer der Im­ple­men­ta­ti­on __next__()-Funktion nichts verändert. Hier wurde ein zu­sätz­li­ches if-else-Statement eingebaut, das überprüft, ob die aktuelle Zahl kleiner oder gleich 100 ist und nur unter dieser Bedingung weiter durch die Menge der geraden Zahlen iteriert. Wenn die Zahl den Wert 100 über­steigt, wird durch den Aufruf von Sto­pI­te­ra­ti­on ein Fehler ausgelöst.

Zum Hauptmenü