Modulelessen (3/4)
Generator-expressie
Een generatorexpressie is als een lijstbegrip, maar dan met haakjes in plaats van vierkante haakjes. Het verschil is dramatisch: het bouwt geen lijst op in het geheugen, het produceert elementen on-demand, één voor één.
gen = (n * n for n in range(1_000_000))
# istantaneo, memoria costante: nessun calcolo ancora fatto
list_comp = [n * n for n in range(1_000_000)]
# alloca 1M di int in memoriaLuiheid (luie evaluatie)
De generator doet niets totdat iemand om de volgende waarde vraagt:
gen = (n * n for n in range(5))
next(gen) # 0 (calcolato adesso)
next(gen) # 1
next(gen) # 4
# ... e così via, fino a StopIterationHet raakt uitgeput: na het consumeren van alle elementen is het voor altijd leeg. Om het opnieuw te kunnen gebruiken, moet u het opnieuw maken.
Wanneer moet u het gebruiken?
Wanneer u de resultaten doorgeeft aan een functie die ze in volgorde verbruikt:
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costantesum, any, all, max, min, "".join(...) accepteren allemaal generatoren.
Als de buitenste functie alleen de aanroephaakjes vereist, is dat mogelijk
laat die van de generator weg:
sum((n * n for n in range(10))) # OK
sum(n * n for n in range(10)) # IDENTICO, più leggibileany en all: kortsluiting
any(...) en all(...) stoppen met herhalen zodra ze het antwoord hebben.
Met een generator worden de volgende elementen niet eens berekend.
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums) # True (si ferma a 4)
all(n > 0 for n in nums) # True
all(n > 2 for n in nums) # False (si ferma a 1)Patroon: luie pijplijn
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
prime_dieci.append(r)
if len(prime_dieci) == 10:
breakGeen tussenlijst, zelfs niet bij grote inputs.
Generatoren verbruiken met som, alles, alles
Generatorexpressies zijn perfect om rechtstreeks door te geven aan functies die iterabelen gebruiken, zoals sum(), any() of all(). In dit geval kunt u de buitenste haakjes van de generatoruitdrukking weglaten door simpelweg te schrijven:
squares_sum = sum(x**2 for x in range(10))Hierdoor blijft uw code schoon en zeer geheugenefficiënt.
Probeer het
Bereken de som van de kwadraten van de getallen van 1 tot en met 100 met behulp van een generatorexpressie binnen sum(). Wijs het toe aan 'tot'. Evalueer 'tot'.
Toon hint
bereik(1, 101) omvat 100.
Oplossing beschikbaar na 3 pogingen
Oefening beoordelen
Gegeven `words = ['ciao', 'mondo', 'PYTHON', 'java']`, gebruik any() met een generatorexpressie om te controleren of MINSTENS één woord hoofdletters is (.isupper()). Wijs het resultaat toe aan `has_uppercase`. Evalueer `heeft_hoofdletter`.
Toon hint
any(p.isupper() voor p in woorden)
Oplossing beschikbaar na 3 pogingen
Extra uitdaging
Use a generator expression passed directly to the `sum()` function to calculate the sum of the squares of all integers from 1 to 100 inclusive. Store the result in `total_sum` and evaluate it.
Toon hint
Schrijf totaal_som = som(x**2 voor x binnen bereik(1, 101)). Dubbele haakjes zijn niet nodig.
Oplossing beschikbaar na 3 pogingen