Unterscheidung zwischen Iterator und Generator in Python
Iteratoren und Generatoren helfen uns dabei, eine Ausgabe zu generieren oder Code iterativ Bit für Bit zu verarbeiten. In diesem Artikel lernen wir anhand eines einfachen Beispiels einige grundlegende Unterschiede zwischen den Iteratoren und Generatoren von Python kennen.
Iterator in Python
Die grundlegenden Funktionen eines Iterators sind wie folgt:
- Ein Iterator ist ein Objekt, das mit einer Klasse erstellt wurde, die das Iteratorprotokoll implementiert. Das bedeutet, dass die Klasse die Methoden
__iter__
und__next__
definiert hat. - Die Methode
__next__
verwendet diereturn
-Anweisung, um einen Wert zurückzugeben. Da diereturn
-Anweisung die letzte Zeile in dieser Methode sein muss, müssen wir die Variable aktualisieren, die beim nächsten Durchlauf von__next__
vor derreturn
-Anweisung verwendet werden soll.
Im einfachsten Fall sehen wir uns an, __iter__
gibt self
zurück.
Generator in Python
Die grundlegenden Merkmale eines Generators sind wie folgt:
- Ein Generator ist eine Funktion.
- Eine Generatorfunktion verwendet das Schlüsselwort
yield
anstelle des Schlüsselwortsreturn
.
2.1 Das Schlüsselwortyield
liefert einen Wert und unterbricht die Ausführung der Funktion.
2.2 Der nächste Aufruf vonnext()
setzt die Ausführung des Codes nach deryield
-Anweisung fort.
Eine Generatorfunktion ermöglicht es uns, einen Generator-Iterator ohne den gesamten zusätzlichen Code zu erstellen, der beim Erstellen eines Iterators mit einer Klasse erforderlich ist.
Beispiele für Iterator und Generator in Python
Die folgenden beiden Beispiele verdeutlichen die in den beiden vorangegangenen Abschnitten erwähnten Punkte. Beide Beispiele veranschaulichen, wie man Quadrate von ganzen Zahlen erzeugt, beginnend mit 1.
Das erste Beispiel zeigt, wie es mit einem Iterator gemacht wird. Das zweite Beispiel zeigt äquivalenten Code mit einem Generator.
Beispielcode für Iterator:
# ITERATOR (Class)
class squares(object):
def __init__(self, num1):
self.nxt_sq_of = 1
self.lim = num1
def __iter__(self):
return self
def __next__(self):
if self.nxt_sq_of <= self.lim:
ret_sq_of = self.nxt_sq_of
self.nxt_sq_of += 1
return ret_sq_of * ret_sq_of
else:
raise StopIteration
# Iterator Object
a = squares(6)
# Next value of the iterator.
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
next(a)
# Using the iterator in a loop.
a1 = squares(6)
while True:
print(next(a1))
Ausgabe:
next(a)
Out[3]: 1
next(a)
Out[4]: 4
next(a)
Out[5]: 9
next(a)
Out[6]: 16
next(a)
Out[7]: 25
next(a)
Out[8]: 36
next(a)
Traceback (most recent call last):
File "<ipython-input-9-15841f3f11d4>", line 1, in <module>
next(a)
File "<ipython-input-1-9dbe8e565876>", line 17, in __next__
raise StopIteration
StopIteration
Beispielcode für Generator:
# GENERATOR FUNCTION
def gen_squares(num2):
i = 1
while i <= num2:
yield i * i
i += 1
# Generator iterator.
b = gen_squares(5)
# Next yield of the generator iterator.
next(b)
next(b)
next(b)
next(b)
next(b)
next(b)
Ausgabe:
next(b)
Out[3]: 1
next(b)
Out[4]: 4
next(b)
Out[5]: 9
next(b)
Out[6]: 16
next(b)
Out[7]: 25
next(b)
Traceback (most recent call last):
File "<ipython-input-8-adb3e17b0219>", line 1, in <module>
next(b)
StopIteration
Fazit
Wir stellen fest, dass die Generatoren von Python es uns ermöglichen, prägnanten Code zu schreiben, um einen Generator-Iterator zu erstellen.
Iteratoren hingegen sind viel leistungsfähiger, da sie es dem Programmierer ermöglichen, benutzerdefinierten Code für die Methode __iter__
zu schreiben.
Weitere Einzelheiten finden Sie im Folgenden.
- Python-Wiki-Artikel für Generatoren.
- Python-Wiki-Artikel für Iteratoren.