Salt la conținutul principal
Modulul 6 · Lecția 3 din 423/36 în curs~10 min
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.

Python
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 memoria

Lene (evaluare leneșă)

Generatorul nu face nimic până când cineva cere următoarea valoare:

Python
gen = (n * n for n in range(5))
next(gen)    # 0    (calcolato adesso)
next(gen)    # 1
next(gen)    # 4
# ... e così via, fino a StopIteration

Se 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:

Python
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costante

sum, any, all, max, min, "".join(...) toți acceptă generatoare. Dacă funcția exterioară necesită doar parantezele de apel, puteți omite generatorul propriu:

Python
sum((n * n for n in range(10)))    # OK
sum(n * n for n in range(10))      # IDENTICO, più leggibile

any ș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.

Python
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șă

Python
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:
        break

Nicio 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:

Python
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ă

Exercițiu#python.m6.l3.e1
Încercări: 0Se încarcă…

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`.

Se încarcă editorul...
Afișează indiciu

intervalul (1, 101) include 100.

Soluție disponibilă după 3 încercări

Exercițiu de revizuire

Exercițiu#python.m6.l3.e2
Încercări: 0Se încarcă…

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`.

Se încarcă editorul...
Afișează indiciu

orice(p.isupper() pentru p în cuvinte)

Soluție disponibilă după 3 încercări

Provocare suplimentară

Exercițiu#python.m6.l3.e3
Încercări: 0Se încarcă…

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.

Se încarcă editorul...
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