ProgrammatiePython ontwikkelaar

Leg uit wat generatoren zijn in Python. Hoe werken ze, waarvoor worden ze gebruikt, en wat is het verschil met lijstexpressies?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

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:

  • Lijstexpressies ([x for x in range(10)]) creëren onmiddellijk de hele lijst in het geheugen.
  • Generatoren ((x for x in range(10))) creëren elementen één voor één, en verbruiken veel minder geheugen.

Wanneer generatoren gebruiken:

  • Als er geen toegang tot elementen via index nodig is.
  • Als de gegevens te groot zijn om in het geheugen op te slaan.
  • Bij het organiseren van streaming gegevensverwerking (bijvoorbeeld het lezen van regel voor regel van een bestand).
# Generatorfunctie def counter(n): for i in range(n): yield i for number in counter(5): print(number)

Misleidende vraag.

"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

Voorbeelden van echte fouten door onbekendheid met de subtiele punten van het onderwerp.


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.