Iteratory i generatory to podstawa efektywnego przetwarzania sekwencji w Pythonie. Historycznie Python dążył do uproszczenia pracy z strumieniami danych i unikania nadmiernego przechowywania dużych kolekcji w pamięci. Najpierw wprowadzono wsparcie dla iteratorów za pomocą protokołów __iter__ i __next__, a następnie — generatory, które pozwalają na tworzenie najprostszych iteratorów za pomocą konstrukcji opartych na yield.
Problem: często konieczne jest przetwarzanie dużych ilości danych (np. strumieniowanie z pliku lub bazy danych), co nie jest wygodne i efektywne, jeśli wczytujemy wszystko do pamięci od razu. Zwykłe funkcje zwracają wszystkie wyniki naraz, a tworzenie własnych iteratorów za pomocą klas jest często zbyt skomplikowane w prostych przypadkach.
Rozwiązanie: mechanizm yield pozwala na zorganizowanie "leniwego" generowania danych. Funkcja generatora nie zwraca listy ani innej kolekcji, ale zwraca obiekt generatora — iterator, który oblicza wartości w miarę potrzeby.
Przykład kodu:
# Prosty generator def countdown(n): while n > 0: yield n n -= 1 for i in countdown(3): print(i) # 3, 2, 1
Kluczowe cechy:
Czy można używać return i yield w tej samej funkcji?
Tak, ale return w generatorze kończy iterację (wywołuje StopIteration), a yield może być używany dowolną liczbę razy.
def example(): yield 1 return # StopIteration
Dlaczego generator nie może być "zrestartowany" po zakończeniu?
Generator po zakończeniu iteracji (StopIteration) nie może być ponownie uruchomiony, należy go stworzyć na nowo.
gen = countdown(2) list(gen) # [2, 1] list(gen) # [] (generator już wyczerpany)
Jaka jest różnica między generatorem a iteratorem?
Generator to szczególny przypadek iteratora; każdy obiekt z metodami iter i next jest iteratorem, ale generator tworzony jest za pomocą funkcji z yield.
Programista napisał funkcję, która wczytuje milion wierszy pliku do pamięci za pomocą list(fd) do analizy. Doprowadziło to do przepełnienia pamięci na serwerze.
Zalety:
Wady:
Użycie generatora do czytania pliku linia po linii i analizy danych w locie za pomocą yield.
Zalety:
Wady: