Un generator este o funcție care se poate opri și apoi poate continua mai târziu.
Când apelezi o funcție generator, primești înapoi un obiect generator, iar acest obiect este un iterator.
Codul lui nu a rulat încă deloc. Începe să se execute doar când iterezi peste generator.
Exemplu
O funcție generator simplă:
Ieșire: program Python complet
def my_generator():
yield 1
yield 2
yield 3
for value in my_generator():
print(value)
Cuvântul cheie yield
Ceea ce transformă o funcție într-un generator este cuvântul cheie yield.
Când ajunge la un yield, funcția dă înapoi o valoare și își salvează starea. Când generatorului i se cere altă valoare, el continuă exact de unde s-a oprit.
return încheie o funcție definitiv, dar yield doar o întrerupe, așa că o funcție îl poate folosi de mai multe ori.
Exemplu
Un generator care produce, pe rând, o serie de numere:
Ieșire: program Python complet
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
for num in count_up_to(5):
print(num)
Generatorii economisesc memorie
Un generator produce valorile pe măsură ce este nevoie de ele, în loc să le țină pe toate în memorie.
Asta face o diferență reală la seturile mari de date:
Exemplu
Un generator pentru o secvență foarte lungă:
Ieșire: program Python complet
def large_sequence(n):
for i in range(n):
yield i
# Aceasta nu creează un milion de numere în memorie
gen = large_sequence(1000000)
print(next(gen))
print(next(gen))
print(next(gen))
Folosirea next() cu generatori
Funcția next() îți permite să parcurgi manual un generator, pas cu pas.
După ce toate valorile au fost produse, încă un apel ridică o excepție StopIteration.
Exemplu
Ieșire: program Python complet
def simple_gen():
yield "Emil"
yield "Tobias"
yield "Linus"
gen = simple_gen()
print(next(gen))
print(next(gen))
print(next(gen))
Exemplu
Ieșire: program Python complet
def simple_gen():
yield 1
yield 2
gen = simple_gen()
print(next(gen))
print(next(gen))
print(next(gen)) # Aceasta va ridica StopIteration
Expresii generator
Expresiile generator creează generatori cu o sintaxă apropiată de list comprehension. Singura diferență sunt parantezele rotunde în locul celor pătrate:
Exemplu
Un list comprehension alături de o expresie generator:
Ieșire: program Python complet
# List comprehension - creează o listă
list_comp = [x * x for x in range(5)]
print(list_comp)
# Expresie generator - creează un generator
gen_exp = (x * x for x in range(5))
print(gen_exp)
print(list(gen_exp))
Exemplu
Transmiterea unei expresii generator către sum:
Ieșire: program Python complet
# Calculează suma pătratelor fără a crea o listă
total = sum(x * x for x in range(10))
print(total)
Generator pentru șirul Fibonacci
Șirul Fibonacci se potrivește perfect cu un generator.
Poate continua să producă valori la nesfârșit, fără să-ți epuizeze memoria:
Exemplu
Afișează primele 100 de numere Fibonacci:
Ieșire: program Python complet
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Obține primele 100 de numere Fibonacci
gen = fibonacci()
for _ in range(100):
print(next(gen))
Metodele generatorilor
Pentru un control mai avansat, generatorii vin cu câteva metode speciale:
Exemplu
Cu metoda send(), poți transmite o valoare în generator:
Ieșire: program Python complet
def echo_generator():
while True:
received = yield
print("Primit:", received)
gen = echo_generator()
next(gen) # Pregătește generatorul
gen.send("Hello")
gen.send("World")
Exemplu
Metoda close() închide generatorul:
Ieșire: program Python complet
def my_gen():
try:
yield 1
yield 2
yield 3
finally:
print("Generator închis")
gen = my_gen()
print(next(gen))
gen.close()