Iteratoren in Python

In diesem Artikel geht es um Iteratoren in Python. Dazu betrachten wir die Iteration (lat.: iterare, wiederholen). In Python wie – wie auch anderen Programmiersprachen – kann sie mit einer for-Schleife realisiert werden. Mit ihr können beispielsweise Strings und Listen, durchlaufen werden. Nachfolgend zwei Beispiele, bei der mithilfe der for-Schleife die genannten Datenstrukturen durchlaufen und die einzelnen Elemente ausgegeben werden.

Im Falle eines Strings sieht das wie folgt aus:

programming_language = "Python"

for i in programming_language:
    print(i)

P
y
t
h
o
n

Und eine Listen-Iteration sieht dementsprechend so aus:

towns = ["London", "Helsinki", "Nairobi"]

for i in towns:
    print(i)

London
Helsinki
Nairobi

Es lässt sich also festhalten, dass Iteratoren etwas sind, mit denen iterierbare Objekte (Strings, Listen, Tupel, etc.) durchlaufen werden können. Praktisch umgesetzt wird dies beispielsweise mit einer for-Schleife.

Das es sich um iterierbares Objekt handelt, lässt sich übrigens mit iter() überprüfen:

>>> iter(towns)
<list_iterator object at 0x105e074f0>

Die Rückgabe list_iterator object meint ein iterierbares Objekt.

Werfen wir nun aber einen Blick hinter die Kulissen. Wie „entsteht“ ein Iterator und wie ist es möglich, dass bestimmte Datenstrukturen durchlaufen werden können, sie mithin iterierbar sind?

Hier kommen zwei Funktionen ins Spiel:

  • iter() und
  • next().

Mit der Funktion iter() kann ein Iterator von einem iterierbaren Objekt erstellt werden:

>>> iterator = iter(towns)
>>> type(iterator)
<class 'list_iterator'>

Die Funktion next() kann jetzt verwendet werden, um iterator zu durchlaufen:

>>> towns = ["London", "Helsinki", "Nairobi"]
>>> item = iter(towns)
>>> next(item)
'London'
>>> next(item)
'Helsinki'
>>> next(item)
'Nairobi'

Sobald auf alle Elemente der Liste towns zugegriffen wurde, erscheint beim nächsten Versuch eine Fehlermeldung:

>>> next(item)
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    next(item)
StopIteration

Iteratoren folgen dem Iterator Protocol. Objekte, die dieses Protokoll implementiert haben, sind iterierbare Objekte. Das Protokoll beinhaltet zwei besondere Methoden: __iter__() und __next__(). Hierbei handelt es sich um sogenannte magical methods oder dunder methods (dunder steht für double underscore). Die Unterstriche kennzeichnen, in Abgrenzung zu Methoden ohne doppelte Unterstriche, dass es sich um Methoden innerhalb einer Klasse handelt. Sie machen ein Objekt iterierbar. Im Hintergrund rufen die Built-In-funktionen iter() und next() diese beiden dunder methods auf. Die for-Schleife wiederum ist so konzipiert, dass sie mit iterierbaren Objekten funktioniert.

Mit diesem Wissen wäre es möglich, einen eigenen Iterator zu schreiben. Notwendig wäre dabei eine eigene Implementierung von __iter__() und __next()__. Dies soll aber nicht Gegenstand dieses Artikels sein. Vielmehr finden sich im Internet zahlreiche Code-Beispiele für selbst erstellte Iteratoren.