Generatory to specjalne obiekty iterowalne w Pythonie, które pozwalają na tworzenie sekwencji "na bieżąco", nie zajmując pamięci pod całą kolekcję od razu. Są realizowane za pomocą funkcji z użyciem słowa kluczowego yield lub wyrażeń generatorów ((expr for ... in ...)). To jest wygodne podczas pracy z dużymi ilościami danych lub potencjalnie nieskończonymi strumieniami.
Kluczowe różnice w stosunku do wyrażeń listowych:
[x for x in range(10)]) tworzą od razu całą listę w pamięci.(x for x in range(10))) tworzą elementy jeden po drugim, zużywając znacznie mniej pamięci.Kiedy używać generatorów:
# Funkcja generatorowa def counter(n): for i in range(n): yield i for number in counter(5): print(number)
"Jaka jest różnica między używaniem funkcji z yield a zwykłą funkcją, która zwraca listę? Podaj przykład."
Odpowiedź:
Zwykła funkcja natychmiast oblicza i zwraca listę, zajmując pamięć pod wszystkie jej elementy. Funkcja z yield zwraca generator, który wydaje elementy jeden po drugim i nie ładuje całej sekwencji do pamięci od razu.
def make_list(n): return [i for i in range(n)] # Zwróci od razu listę, zajmuje dużo pamięci def make_generator(n): for i in range(n): yield i # Będzie wydawać jeden element
Historia
W projekcie do analizy dużych logów używano wyrażeń listowych do wyodrębnienia wierszy zawierających błędy:
error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]
Plik przekraczał 2 GB, a aplikacja zakończyła działanie z OOM (Out of Memory). Należało użyć generatora:
error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)
Historia
Pracownik chciał przeanalizować krótki wykaz, napisał funkcję z yield, ale zapomniał, że zwracany jest generator, a nie lista:
result = my_generator_function() # result — generator, a nie lista if len(result) > 5: # TypeError: obiekt typu 'generator' nie ma długości
Poprawka: owinąć wynik w list().
Historia
Próbowali iterować po generatorze kilka razy:
numbers = (i for i in range(5)) for n in numbers: pass # wyczerpano generator for n in numbers: print(n) # nic nie wyświetla
Generator jest jednorazowy. Należy stworzyć nowy, aby ponownie go użyć.