Generatoren zijn speciale iterabele objecten in Python die het mogelijk maken om sequenties "terwijl ze lopen" te creëren, zonder geheugen te gebruiken voor de hele collectie tegelijk. Ze worden geïmplementeerd met behulp van functies met het sleutelwoord yield of generatorexpressies ((expr for ... in ...)). Dit is handig bij het werken met grote hoeveelheden gegevens of potentieel oneindige stromen.
Belangrijkste verschillen met lijstexpressies:
[x for x in range(10)]) creëren onmiddellijk de hele lijst in het geheugen.(x for x in range(10))) creëren elementen één voor één, en verbruiken veel minder geheugen.Wanneer generatoren gebruiken:
# Generatorfunctie def counter(n): for i in range(n): yield i for number in counter(5): print(number)
"Wat is het verschil tussen het gebruik van een functie met yield en een gewone functie die een lijst retourneert? Geef een voorbeeld."
Antwoord:
Een gewone functie berekent en retourneert onmiddellijk een lijst, en gebruikt geheugen voor al zijn elementen. Een functie met yield retourneert een generator, die elementen één voor één levert en niet de hele sequentie in één keer in het geheugen laadt.
def make_list(n): return [i for i in range(n)] # Retourneert onmiddellijk een lijst, gebruikt veel geheugen def make_generator(n): for i in range(n): yield i # Levert één element per keer
Verhaal
In een project voor het analyseren van grote logs werden lijstexpressies gebruikt om regels met fouten te isoleren:
error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]
Het bestand overschrijdt 2 GB en de applicatie crashte met OOM (Out of Memory). Een generator had moeten worden gebruikt:
error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)
Verhaal
Een medewerker wilde een korte lijst analyseren, schreef een functie met yield, maar vergat dat een generator werd geretourneerd, niet een lijst:
result = my_generator_function() # result is een generator, geen lijst if len(result) > 5: # TypeError: object of type 'generator' has no len()
Oplossing: wikkel het resultaat in list().
Verhaal
Er werd geprobeerd meerdere keren door de generator te itereren:
numbers = (i for i in range(5)) for n in numbers: pass # generator uitgeput for n in numbers: print(n) # geeft niets weer
Generator is eenmalig. Er moet een nieuwe worden gemaakt voor herhaald gebruik.