CodeGym /Kurse /Python SELF DE /Generatoren

Generatoren

Python SELF DE
Level 13 , Lektion 4
Verfügbar

3.1 Einführung in Generatoren

Generatoren sind Funktionen, die ein Iterator-Objekt zurückgeben. Diese Iteratoren generieren Werte, wenn sie angefordert werden, was es ermöglicht, potenziell große Datensätze zu verarbeiten, ohne sie vollständig in den Speicher zu laden.

Es gibt mehrere Möglichkeiten, Generatoren zu erstellen, unten werden die beliebtesten davon betrachtet.

Generatoren basierend auf Funktionen

Generatoren werden mit dem Schlüsselwort yield innerhalb einer Funktion erstellt. Wenn eine Funktion mit yield aufgerufen wird, gibt sie ein Generator-Objekt zurück, führt aber nicht sofort den Code innerhalb der Funktion aus. Stattdessen wird die Ausführung an der yield-Anweisung angehalten und bei jedem Aufruf der __next__()-Methode des Generator-Objekts fortgesetzt.


def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1
        
counter = count_up_to(5)
print(next(counter))  # Ausgabe: 1
print(next(counter))  # Ausgabe: 2
print(next(counter))  # Ausgabe: 3
print(next(counter))  # Ausgabe: 4
print(next(counter))  # Ausgabe: 5

Wenn eine Funktion das yield-Statement enthält, erstellt Python anstelle der traditionellen Ausführung der Funktion ein Generator-Objekt, das den Zustand der Ausführung der Funktion verwaltet.

Generator-Ausdrücke

Generator-Ausdrücke ähneln List Comprehensions, werden jedoch mit runden statt eckigen Klammern erstellt. Sie geben ebenfalls ein Generator-Objekt zurück.


squares = (x ** 2 for x in range(10))

print(next(squares))  # Ausgabe: 0
print(next(squares))  # Ausgabe: 1
print(next(squares))  # Ausgabe: 4

Welche Variante gefällt dir besser?

3.2 Vorteile von Generatoren

Effiziente Speichernutzung

Generatoren berechnen Werte on-the-fly, was es ermöglicht, große Datenmengen zu verarbeiten, ohne sie vollständig in den Speicher zu laden. Das macht Generatoren zur idealen Wahl für die Arbeit mit großen Datenmengen oder Datenströmen.


def large_range(n):
    for i in range(n):
        yield i
        
for value in large_range(1000000):
    # Verarbeite Werte einzeln
    print(value)

Lazy Evaluation

Generatoren führen lazy Evaluation durch, was bedeutet, dass sie Werte nur dann berechnen, wenn dies erforderlich ist. Dies hilft, unnötige Berechnungen zu vermeiden und die Leistung zu verbessern.


def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b
        
fib = fibonacci()
for _ in range(10):
    print(next(fib))

Bequeme Syntax

Generatoren bieten eine bequeme Syntax zur Erstellung von Iteratoren, was das Schreiben und Lesen von Code vereinfacht.

3.3 Nutzung von Generatoren

Beispiele für die Nutzung von Generatoren in der Standardbibliothek

Viele Funktionen in der Python-Standardbibliothek nutzen Generatoren. Zum Beispiel gibt die Funktion range() ein Generator-Objekt zurück, das eine Sequenz von Zahlen generiert.


for i in range(10):
    print(i)

Ja, die Welt wird nie mehr dieselbe sein.

Erstellung unendlicher Sequenzen

Generatoren ermöglichen die Erstellung unendlicher Sequenzen, die in verschiedenen Szenarien nützlich sein können, wie z.B. der Generierung unendlicher Datenströme.


def natural_numbers():
    n = 1
    while True:
        yield n
        n += 1
        
naturals = natural_numbers()
for _ in range(10):
    print(next(naturals))

Verwendung von send() und close()

Generator-Objekte unterstützen die Methoden send() und close(), die es ermöglichen, Werte zurück in den Generator zu senden und dessen Ausführung zu beenden.


def echo():
    while True:
        received = yield
        print(received)
        
e = echo()
next(e)  # Starte den Generator
e.send("Hallo, Welt!")  # Ausgabe: Hallo, Welt!
e.close()

3.4 Generatoren in der Praxis

Generatoren und Ausnahmen

Generatoren können Ausnahmen behandeln, was sie zu einem mächtigen Werkzeug für das Schreiben von robusterem Code macht.


def controlled_execution():
    try:
        yield "Start"
        yield "Working"
    except GeneratorExit:
        print("Generator geschlossen")
        
gen = controlled_execution()
print(next(gen))  # Ausgabe: Start
print(next(gen))  # Ausgabe: Working
gen.close()  # Ausgabe: Generator geschlossen

Die Arbeit mit Ausnahmen werden wir in den nächsten Vorlesungen genauer betrachten, aber ich denke, es ist nützlich zu wissen, dass Generatoren gut damit umgehen.

Eingebettete Generatoren

Generatoren können ineinander verschachtelt sein, was es ermöglicht, komplexe iterierbare Strukturen zu erstellen.


def generator1():
    yield from range(3)
    yield from "ABC"
        
for value in generator1():
    print(value)

# Ausgabe
0
1
2
A
B
C

Erklärung:

yield from: Diese Konstruktion wird verwendet, um einen Teil der Operationen an einen anderen Generator zu delegieren, was den Code vereinfacht und die Lesbarkeit verbessert.

Generatoren und Leistung

Die Verwendung von Generatoren kann die Leistung von Programmen erheblich verbessern, indem der Speicherverbrauch reduziert und die Iterationen effizienter ausgeführt werden.

Beispielvergleich von Listen und Generatoren


import time
import sys

def memory_usage(obj):
    return sys.getsizeof(obj)

n = 10_000_000

# Nutzung einer Liste
start_time = time.time()
list_comp = [x ** 2 for x in range(n)]
list_time = time.time() - start_time
list_memory = memory_usage(list_comp)

# Nutzung eines Generators
start_time = time.time()
gen_comp = (x ** 2 for x in range(n))
gen_result = sum(gen_comp)  # Berechnen der Summe für vergleichbare Ergebnisse
gen_time = time.time() - start_time
gen_memory = memory_usage(gen_comp)

print(f"Liste:")
print(f"  Zeit: {list_time:.2f} Sek")
print(f"  Speicher: {list_memory:,} Bytes")

print(f"\nGenerator:")
print(f"  Zeit: {gen_time:.2f} Sek")
print(f"  Speicher: {gen_memory:,} Bytes")

Liste:
  Zeit: 0.62 Sek
  Speicher: 89,095,160 Bytes

Generator:
  Zeit: 1.13 Sek
  Speicher: 200 Bytes
1
Umfrage/Quiz
Systemfunktionen, Level 13, Lektion 4
Nicht verfügbar
Systemfunktionen
Systemfunktionen
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION