Generatore
È un oggetto più semplice dell’iteratore. È una funzione che quando ritorna al chiamante, mantiene uno stato interno. Non crea effettivamente una sequenza, ma ha la logica per generarla.
yield prende il posto del return.
# Generator function
def fibonacci():
a = 0
b = 1
while True:
yeald b
a,b = b, a+bIl generatore è composto da due componenti fondamentali:
- generator function
- generatore
La generator function è una funzione che accetta parametri e restituisce un generatore. In realtà non viene restituito nulla perchè per i generatori non viene quindi deallocata la memoria, e quindi è il corpo della funzione il generatore vero e proprio.
Per iterare su un generatore si utilizza la funzione next, proprio come per gli iteratori. Questo impedisce il passaggio di parametri al generatore, una volta istanziato.
La generator function si riconosce dalla presenza di almeno una istruzione yield, solitamente al posto di un return. Quando il programma incontra una istruzione yield, salva lo stato della funzione e ritorna un valore. Quando viene chiamato next(generator_function), riprende dallo stato precedente.
Anche il generatore restituisce StopIteration quando arriva alla fine.
Dichiarazione implicita
Si può utilizzare la stessa struttura della List comprehension per creare un generatore implicitamente:
[<espressione> for <id> in <iterabile> if <condizione>]
Moreover
I generatori possono anche essere utilizzati in un ciclo for:
def fibonacci(n):
'''Trasformazione della funzione in generatore. L'istruzione yield
semplicemente sostituisce la stampa.
'''
a = 0
b = 1
yield a
for _ in range(n-2):
yield b
a,b = b,a+b
yield b
for i in fibonacci(6):
print(i)Si può creare un simil range basto su un generatore:
def rangegen(*params):
'''Generatore che simula l'iterabile range'''
#### Controllo dei parametri e "setting" valori iniziale, finale e passo ####
assert len(params)>=1 and len(params)<=3,"Illegal number of parameters"
for x in params:
if type(x) is not int:
raise TypeError(f"'{type(x)}' object cannot be interpreted as an integer")
if len(params)==1:
start = 0
step = 1
end = params[0]
else:
start = params[0]
end = params[1]
step = 1 if len(params)==2 else params[2]
###############################################################################
i = start
while step>0 and i<end or step<0 and i>end:
yield i
i += step