Python Generatoren (yield): Effizient & speicherschonend

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Generatoren in Python sind ein mächtiges Werkzeug für die effiziente Arbeit mit Datenfolgen. Sie ermöglichen die Erstellung von iterierbaren Objekten, die Werte nur bei Bedarf berechnen und so den Systemspeicher erheblich schonen. Die Grundlage von Generatoren ist das Schlüsselwort yield, das sich grundlegend von der traditionellen return-Anweisung unterscheidet.

Grundlagen der Python-Generatoren

Generatoren sind spezielle Funktionen, die anstelle konkreter Werte einen Iterator zurückgeben. Der Hauptunterschied liegt in der Verwendung des Schlüsselworts yield, das den Zustand der Funktion zwischen den Aufrufen speichert.

Bei jedem Aufruf der Generatorfunktion wird die Ausführung an der Stelle fortgesetzt, an der die letzte yield-Anweisung gestoppt wurde. Das macht Generatoren zur idealen Lösung für die Verarbeitung großer Datenströme, ohne dass diese vollständig im Speicher abgelegt werden müssen.

def einfacher_generator():
    yield 1
    yield 2
    yield 3

gen = einfacher_generator()
for wert in gen:
    print(wert)

Ausgabe:

1
2
3

So funktioniert das Schlüsselwort yield

Das Schlüsselwort yield arbeitet nach dem Prinzip der "lazy evaluation" (faulen Berechnung):

  1. Beim ersten Aufruf von next() beginnt die Ausführung am Anfang der Funktion bis zum ersten yield
  2. Nach der Rückgabe des Werts "friert" die Funktion ihren Zustand ein
  3. Der nächste Aufruf von next() setzt die Ausführung an der Stoppstelle fort
  4. Dieser Prozess wird bis zum Ende der Funktion fortgesetzt
def zaehler():
    print("Generator gestartet")
    yield 1
    print("Nach dem ersten yield")
    yield 2
    print("Nach dem zweiten yield")

gen = zaehler()
next(gen)  # Ausgabe: Generator gestartet
next(gen)  # Ausgabe: Nach dem ersten yield

Vorteile von Generatoren gegenüber Listen

Die Verwendung von Generatoren anstelle von Listen bietet erhebliche Vorteile bei der Arbeit mit großen Datenmengen:

Speicherschonend: Generatoren speichern nicht alle Werte gleichzeitig, sondern erzeugen sie bei Bedarf.

# Liste - benötigt viel Speicher
quadrate_liste = [x * x for x in range(1000000)]

# Generator - minimaler Speicherverbrauch
quadrate_gen = (x * x for x in range(1000000))

Performance: Generatoren liefern sofort Werte zurück, ohne auf die Erstellung der gesamten Sequenz warten zu müssen.

Erstellung unendlicher Sequenzen

Mit Generatoren lassen sich unendliche Sequenzen erstellen, ohne dass ein Speicherüberlauf riskiert wird:

def unendlicher_zaehler(start=0):
    while True:
        yield start
        start += 1

zaehler = unendlicher_zaehler()
print(next(zaehler))  # 0
print(next(zaehler))  # 1
print(next(zaehler))  # 2

Methoden zur Arbeit mit Generatoren

Generatoren unterstützen mehrere spezialisierte Methoden:

next() — Holt den nächsten Wert aus dem Generator send(value) — Sendet einen Wert in den Generator throw() — Löst eine Ausnahme innerhalb des Generators aus close() — Stoppt den Generator zwangsweise

def interaktiver_generator():
    wert = yield "Start"
    while True:
        wert = yield f"Erhalten: {wert}"

gen = interaktiver_generator()
print(next(gen))           # Start
print(gen.send(42))        # Erhalten: 42
print(gen.send("Hallo"))   # Erhalten: Hallo

Ausnahmebehandlung in Generatoren

Generatoren unterstützen die Ausnahmebehandlung, einschließlich der speziellen Ausnahme GeneratorExit:

def beispiel_generator():
    try:
        yield 1
        yield 2
    except GeneratorExit:
        print("Generator geschlossen!")

gen = beispiel_generator()
print(next(gen))  # 1
gen.close()       # Ausgabe: Generator geschlossen!

Blogs

Buchempfehlungen