Iteratoren en generators zijn de basis voor effectieve verwerking van sequensen in Python. Historisch gezien heeft Python geprobeerd om het werken met gegevensstromen te vereenvoudigen en overbodige opslag van grote verzamelingen in het geheugen te vermijden. Eerst kwam de ondersteuning voor iteratoren via de protocollen __iter__ en __next__, en daarna de generators, die het mogelijk maken om eenvoudigere iteratoren te creëren met behulp van constructies op basis van yield.
Probleem: Het is vaak nodig om grote hoeveelheden gegevens te verwerken (bijvoorbeeld streaming van een bestand of database), wat niet gemakkelijk en efficiënt kan worden gedaan als alles tegelijkertijd in het geheugen wordt geladen. Gewone functies geven alle resultaten tegelijkertijd terug, en het creëren van eigen iteratoren via klassen is vaak te omslachtig voor simpele gevallen.
Oplossing: Het yield-mechanisme maakt het mogelijk om "luie" gegevensgeneratie te organiseren. Een generatorfunctie retourneert geen lijst of andere verzameling, maar retourneert een generatorobject — een iterator die waarden berekent wanneer dat nodig is.
Voorbeeldcode:
# Eenvoudige generator def countdown(n): while n > 0: yield n n -= 1 for i in countdown(3): print(i) # 3, 2, 1
Belangrijke kenmerken:
Kan je return en yield in dezelfde functie gebruiken?
Ja, maar return in een generator beëindigt de iteratie (gooit StopIteration), en yield kan onbeperkt worden gebruikt.
def example(): yield 1 return # StopIteration
Waarom kan een generator niet "herstart" worden na voltooiing?
Een generator kan na het einde van de iteraties (StopIteration) niet opnieuw worden gestart, deze moet opnieuw worden aangemaakt.
gen = countdown(2) list(gen) # [2, 1] list(gen) # [] (generator is al uitgeput)
Wat is het verschil tussen een generator en een iterator?
Een generator is een speciaal geval van een iterator; elk object met de methoden iter en next is een iterator, maar een generator wordt aangemaakt via een functie met yield.
Een ontwikkelaar schreef een functie die een miljoen regels uit een bestand in het geheugen laadt via list(fd) voor analyse. Dit leidde tot geheugenoverload op de server.
Voordelen:
Nadelen:
Gebruik van een generator voor regelgewijs lezen van een bestand (één regel tegelijk) en realtime gegevensanalyse met behulp van yield.
Voordelen:
Nadelen: