Generatoren sind spezielle iterierbare Objekte in Python, die es ermöglichen, Sequenzen "on-the-fly" zu erstellen, ohne den gesamten Speicher für die gesamte Sammlung sofort zu belegen. Sie werden durch Funktionen mit dem Schlüsselwort yield oder durch Generatorausdrücke ((expr for ... in ...)) implementiert. Dies ist nützlich beim Arbeiten mit großen Datenmengen oder potenziell unendlichen Datenströmen.
Wesentliche Unterschiede zu Listenverständnissen:
[x for x in range(10)]) erstellen sofort die gesamte Liste im Speicher.(x for x in range(10))) erzeugen die Elemente einzeln und verbrauchen dabei viel weniger Speicher.Wann Generatoren verwenden:
# Generatorfunktion def counter(n): for i in range(n): yield i for number in counter(5): print(number)
"Was ist der Unterschied zwischen der Verwendung einer Funktion mit yield und einer normalen Funktion, die eine Liste zurückgibt? Geben Sie ein Beispiel an."
Antwort:
Eine normale Funktion berechnet und gibt sofort eine Liste zurück, wobei der Speicher für alle ihre Elemente belegt wird. Eine Funktion mit yield gibt einen Generator zurück, der die Elemente einzeln bereitstellt und nicht die gesamte Sequenz auf einmal im Speicher lädt.
def make_list(n): return [i for i in range(n)] # Gibt sofort eine Liste zurück, belegt viel Speicher def make_generator(n): for i in range(n): yield i # Gibt die Elemente einzeln aus
Geschichte
Im Projekt zur Analyse großer Logs wurden Listenverständnisse verwendet, um Zeilen zu extrahieren, die Fehler enthalten:
error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]
Die Datei überstieg 2 GB und die Anwendung fiel mit OOM (Out of Memory) aus. Es hätte ein Generator verwendet werden müssen:
error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)
Geschichte
Ein Mitarbeiter wollte eine kurze Liste analysieren, schrieb eine Funktion mit yield, vergaß jedoch, dass ein Generator zurückgegeben wird und nicht eine Liste:
result = my_generator_function() # result ist ein Generator, keine Liste if len(result) > 5: # TypeError: object of type 'generator' has no len()
Korrektur: das Ergebnis in list() einpacken.
Geschichte
Es wurde versucht, mehrmals über einen Generator zu iterieren:
numbers = (i for i in range(5)) for n in numbers: pass # Generator erschöpft for n in numbers: print(n) # gibt nichts aus
Generatoren sind einmalig. Es muss ein neuer erstellt werden, um ihn erneut zu verwenden.