Lecții din modul (3/4)
Generator de expresie
O expresie generatoare este ca o listă de înțelegere, dar cu paranteze în loc de paranteze pătrate. Diferența este dramatică: nu construiește o listă în memorie, produce elemente la cerere, pe rând.
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 memoriaLene (evaluare leneșă)
Generatorul nu face nimic până când cineva cere următoarea valoare:
gen = (n * n for n in range(5))
next(gen) # 0 (calcolato adesso)
next(gen) # 1
next(gen) # 4
# ... e così via, fino a StopIterationSe epuizează: după ce consumă toate elementele, este gol pentru totdeauna. Pentru a o reutiliza, trebuie să o recreați.
Când să-l folosești
Când treceți rezultatele unei funcții care le consumă în succesiune:
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costantesum, any, all, max, min, "".join(...) toți acceptă generatoare.
Dacă funcția exterioară necesită doar parantezele de apel, puteți
omite generatorul propriu:
sum((n * n for n in range(10))) # OK
sum(n * n for n in range(10)) # IDENTICO, più leggibileany și all: scurtcircuit
any(...) și all(...) nu mai repetă de îndată ce au răspunsul.
Cu un generator, următoarele elemente nici măcar nu sunt calculate.
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)Model: conductă leneșă
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:
breakNicio listă intermediară, chiar și pentru intrări uriașe.
Consumatoare de generatoare cu suma, oricare, toate
Expresiile generatoare sunt perfecte pentru a trece direct la funcții care consumă iterabile, cum ar fi sum(), any() sau all(). În acest caz, puteți omite parantezele exterioare ale expresiei generatoare, scriind pur și simplu:
squares_sum = sum(x**2 for x in range(10))Acest lucru vă menține codul curat și extrem de eficient din punct de vedere al memoriei.
Încearcă
Calculați suma pătratelor numerelor de la 1 la 100 (inclusiv) folosind o expresie generatoare din interiorul sum(). Atribuiți-o lui `tot`. Evaluează `tot`.
Afișează indiciu
intervalul (1, 101) include 100.
Soluție disponibilă după 3 încercări
Exercițiu de revizuire
Având în vedere `words = ['ciao', 'mondo', 'PYTHON', 'java']`, utilizaţi any() cu o expresie generatoare pentru a verifica dacă MĂRÂNU un cuvânt este majuscule (.isupper()). Atribuiți rezultatul la `has_uppercase`. Evaluați `has_uppercase`.
Afișează indiciu
orice(p.isupper() pentru p în cuvinte)
Soluție disponibilă după 3 încercări
Provocare suplimentară
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.
Afișează indiciu
Scrieți total_sum = sum(x**2 pentru x în interval (1, 101)). Nu sunt necesare paranteze duble.
Soluție disponibilă după 3 încercări