Direkt zum Hauptinhalt springen
eLearner.app
Modul 6 · Lektion 3 von 423/36 im Kurs~10 min
Lektionen des Moduls (3/4)

Generator-Ausdrücke

Eine Generator Expression (Generatorausdruck) ähnelt einer List Comprehension, verwendet jedoch runde Klammern anstelle von eckigen Klammern. Der Unterschied ist enorm: Sie baut keine Liste im Speicher auf, sondern erzeugt Elemente bei Bedarf (on-demand), einzeln nacheinander.

Python
gen = (n * n for n in range(1_000_000))
# sofort, konstanter Speicher: noch keine Berechnung durchgeführt

list_comp = [n * n for n in range(1_000_000)]
# belegt Speicher für 1 Mio. Ganzzahlen

Laziness (Verzögerte Auswertung)

Der Generator tut nichts, bis jemand nach dem nächsten Wert fragt:

Python
gen = (n * n for n in range(5))
next(gen)    # 0    (jetzt berechnet)
next(gen)    # 1
next(gen)    # 4
# ... und so weiter, bis StopIteration

Er erschöpft sich: Nach dem Konsumieren aller Elemente ist er für immer leer. Um ihn wiederzuverwenden, musst du ihn neu erstellen.

Wann man Generator Expressions verwendet

Wenn du die Ergebnisse an eine Funktion übergibst, die sie nacheinander konsumiert:

Python
total = sum(n * n for n in range(1_000_000))
# keine Zwischenliste, konstanter Speicher

sum, any, all, max, min, "".join(...) akzeptieren alle Generatoren. Wenn die äußere Funktion nur die Aufrufklammern benötigt, kannst du die eigenen Klammern des Generators weglassen:

Python
sum((n * n for n in range(10)))    # OK
sum(n * n for n in range(10))      # IDENTISCH, lesbarer

any und all: Kurzschlussauswertung (Short-circuit)

any(...) und all(...) stoppen die Iteration, sobald sie die Antwort kennen. Mit einem Generator werden die nachfolgenden Elemente gar nicht erst berechnet.

Python
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums)    # True (stoppt bei 4)
all(n > 0 for n in nums)    # True
all(n > 2 for n in nums)    # False (stoppt bei 1)

Muster: Lazy Pipeline

Python
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
    prime_dieci.append(r)
    if len(prime_dieci) == 10:
        break

Keine Zwischenlisten, selbst bei riesigen Eingaben.

Konsumieren von Generatoren mit sum, any, all

Generator Expressions eignen sich hervorragend für die direkte Übergabe an Funktionen, die Iterables konsumieren, wie sum(), any() oder all(). In diesem Fall kannst du die äußeren Klammern der Generator Expression weglassen und einfach schreiben:

Python
squares_sum = sum(x**2 for x in range(10))

Dies hält deinen Code sauber und äußerst speichereffizient.

Probiere es aus

Übung#python.m6.l3.e1
Versuche: 0Wird geladen…

Berechne die Summe der Quadrate der Zahlen von 1 bis einschließlich 100 mithilfe eines Generatorausdrucks innerhalb von sum(). Weise das Ergebnis `tot` zu. Evaluiere `tot`.

Editor wird geladen…
Hinweis anzeigen

range(1, 101) schließt 100 ein.

Lösung nach 3 Versuchen verfügbar

Wiederholungsübung

Übung#python.m6.l3.e2
Versuche: 0Wird geladen…

Gegeben sei `words = ['ciao', 'mondo', 'PYTHON', 'java']`. Verwende any() mit einer Generator Expression, um zu prüfen, ob MINDESTENS ein Wort komplett in Großbuchstaben geschrieben ist (.isupper()). Weise das Ergebnis `has_uppercase` zu. Evaluiere `has_uppercase`.

Editor wird geladen…
Hinweis anzeigen

any(p.isupper() for p in words)

Lösung nach 3 Versuchen verfügbar

Zusätzliche Herausforderung

Übung#python.m6.l3.e3
Versuche: 0Wird geladen…

Verwende einen Generatorausdruck, der direkt an die Funktion `sum()` übergeben wird, um die Summe der Quadrate aller Ganzzahlen von 1 bis einschließlich 100 zu berechnen. Speichere das Ergebnis in `total_sum` und evaluiere es.

Editor wird geladen…
Hinweis anzeigen

Schreibe total_sum = sum(x**2 for x in range(1, 101)). Doppelte Klammern sind nicht erforderlich.

Lösung nach 3 Versuchen verfügbar