Generatory Pythona: iteratory oszczędzające pamięć

Dowiedz się, jak używać generatorów języka Python i instrukcji Yield do przetwarzania ogromnych zbiorów danych przy minimalnym zużyciu pamięci. Wyrażenia generatora głównego.

Spróbuj w Edytorze

Przegląd

Podczas pisania kodu przetwarzającego tysiące lub miliony rekordów zarządzanie pamięcią staje się krytyczne. Jeśli załadujesz cały zestaw danych na listę, ryzykujesz wyczerpaniem się pamięci RAM i awarią serwera. Generatory Pythona rozwiązują ten problem, udostępniając mechanizm strumieniowego przesyłania danych na żądanie. Zamiast obliczać i przechowywać jednocześnie cały zbiór danych w pamięci, generator tworzy pojedynczo jeden element, przekazuje go wywołującemu i wstrzymuje jego wykonanie do czasu zażądania następnego elementu.

Generatory są zdefiniowane jak normalne funkcje, ale używają słowa kluczowego `yield` zamiast `return`. Po wywołaniu funkcja generatora zwraca obiekt iteratora generatora bez wykonywania wewnętrznych instrukcji funkcji. Kiedy osoba wywołująca wywołuje `next()` na generatorze (lub wykonuje pętlę po nim), funkcja jest wykonywana aż do osiągnięcia `yield`. W tym momencie generator podaje wartość, zapisuje zmienne lokalne i zawiesza wykonywanie. Po ponownym wywołaniu wznawia dokładnie tam, gdzie został przerwany.

Generatory można także tworzyć przy użyciu wyrażeń generatora, które używają składni identycznej ze znakami listowymi, ale są ujęte w nawiasy `(...)` zamiast nawiasów `[...]`. Dzięki temu niezwykle łatwo jest zastąpić wyrażenia listowe iteratorami oszczędzającymi pamięć. Unikając ogromnych alokacji pamięci, generatory są niezbędne do pracy z dużymi logami, przesyłania strumieniowego danych z baz danych lub wykonywania obliczeń na ciągach matematycznych o nieskończonej długości.

Dane wyjściowe kodu i wykonania

Niestandardowy generator generujący liczby Fibonacciego i wyrażenie generatora oszczędzające pamięć.

generators_demo.py
Spróbuj w Edytorze
def fibonacci_generator(limit):
    """Yields Fibonacci numbers up to the limit."""
    a, b = 0, 1
    count = 0
    while count < limit:
        yield a
        a, b = b, a + b
        count += 1

# Instantiate generator
fib = fibonacci_generator(5)
print("--- Using Generator Function ---")
for num in fib:
    print(num)

# Generator expression (squares of numbers)
squares_gen = (x**2 for x in range(1, 1000000))
print("\n--- Using Generator Expression ---")
print(next(squares_gen))
print(next(squares_gen))
print(next(squares_gen))
Wyjście terminala
--- Using Generator Function ---
0
1
1
2
3

--- Using Generator Expression ---
1
4
9

Wdrażanie krok po kroku

  • Odczytywanie plików linia po linii, które są zbyt duże dla pamięci RAM
  • Generowanie nieskończonej sekwencji identyfikatorów lub cyfr matematycznych
  • Przesyłanie strumieniowe rekordów bazy danych partiami w celu przetwarzania wywołań API

Często zadawane pytania

Jaka jest różnica między zyskiem a zwrotem?

return całkowicie kończy funkcję. Wydajność zwraca wartość i wstrzymuje funkcję, zapisując jej stan, aby mogła zostać wznowiona na żądanie.

Co się stanie, gdy w generatorze skończą się przedmioty?

Zgłasza wyjątek StopIteration. W pętli „for” Python automatycznie przechwytuje ten wyjątek, aby czysto zakończyć pętlę.

Powiązane tematy

Polecane zasoby Pythona

Poszerzaj swoją wiedzę dzięki powiązanym interaktywnym samouczkom, ściągawkom i porównaniom kodów.