Die faule Auswertung (lazy evaluation) ist ein zentrales Konzept des effektiven Programmierens, bei dem Werte nur nach Bedarf berechnet werden. Historisch waren in Python alle wesentlichen eingebauten Strukturen (Listen, Tupel) "gierig": Sie erstellen und speichern alle Elemente im Voraus im Speicher. Mit dem Wachstum der Datenmengen und der Anforderungen an die Datenstromverarbeitung entstand das Bedürfnis nach faulen Berechnungen.
Problem: Gierige Berechnungen führen zu einer ineffizienten Nutzung von Speicher und Zeit, wo Ergebnisse schrittweise erzielt werden können — zum Beispiel beim Filtern, Transformieren großer Sammlungen oder beim Streaming von Dateien.
Lösung: In Python sind viele Werkzeuge für faule Berechnungen entstanden: Generatoren, Iteratoren sowie Funktionen der Standardbibliothek (map, filter, zip, enumerate) und das Modul itertools. Sie geben keine fertigen Sammlungen zurück, sondern "faule" Objekte, die das Ergebnis jeweils einzeln liefern.
Beispielcode:
result = map(lambda x: x * x, range(100)) # gibt einen Generator-Iterator zurück for y in result: print(y) # Werte werden bei der Iteration berechnet import itertools inf = itertools.count(1) for i in inf: if i > 3: break print(i) # 1, 2, 3
Hauptmerkmale:
Geben die Funktionen map/filter immer eine Liste in Python3 zurück?
Nein, in Python 3 geben diese Funktionen Iteratoren und keine Listen zurück. Um eine Liste zu erhalten, muss das Ergebnis in list() gewickelt werden.
x = map(int, ['1', '2']) # <map object> list(x) # [1, 2]
Kann man die Länge des Ergebnisses von map ohne Umwandlung in eine Liste erhalten?
Nein, der Iterator weiß nicht im Voraus, wie viele Elemente er hat, bis er alle durchlaufen hat. Man muss list() verwenden, was die Faulheit aufhebt.
Ist die Funktion range in Python3 gierig oder faul?
Faul: range erstellt ein "Range-Objekt" — es "berechnet" die Elemente auf Anfrage, ohne die gesamte Sequenz zu speichern.
Ein Skript verarbeitet eine riesige CSV-Datei, indem es eine Liste aller Zeilen durch list(open(f)) erstellt. Der Server "stirbt" an Speichermangel bei einer großen Datei.
Vorteile:
Nachteile:
Der Code verwendet faule Verarbeitung: Er durchläuft die Zeilen der Datei mit einem Iterator for line in open(f), oder verarbeitet sie über map/filter, ohne Zwischenkollektionen zu erstellen.
Vorteile:
Nachteile: