Cosa significa “yield”? A che cosa serve?

di Lorenzo Neri
0 commento 105 visualizzazioni

yield è un termine che può lasciare abbastanza confusi quando si programma, soprattutto quando si comincia a scoprire cose più avanzate nel mondo della programmazione.

Ma naturalmente, questo articolo è stato scritto col minor tecnichese possibile per spiegarti cosa significa “yeld” e a che cosa serve 😀

Prima di scoprire la potenza della “yield”, dobbiamo fare un paio di passi indietro.

Se ti dicessi “iterabile” la tua faccia è molto probabile che sia più o meno così 

confused the big lebowski GIF

Ma se ti dicessi invece: posso prendere una lista di numeri interi e stampare a video ogni singolo elemento con un solo ciclo?

Penso che la tua risposta sia “sì!” e più o meno l’aspetto del ciclo sarebbe più o meno questo, usiamo Python per comodità:

lista=[1,2,3]
for elemento in lista:
	print(elemento)

Niente di troppo strano giusto? 

Bene, se pensiamo a quello che abbiamo appena scritto, abbiamo iterato la lista.

La lista è un elemento iterabile.

Ecco cosa è un iterabile

In parole molto semplici, un elemento iterabile è qualcosa che può essere letto o modificato un passo alla volta, quindi attraverso un’iterazione, nel nostro caso un ciclo.

Facciamo un altro passo indietro.

Se ti chiedessi di crearmi una lista “al volo” che contiene i primi 4 numeri interi elevati alla potenza di 2?

Credo che tu stia pensando a qualcosa come:

listaGenerata = [numero*numero for numero in range(4)]

Se poi volessi stamparne il contenuto a video:

for numeroAllaSeconda in listaGenerata:
    print(numeroAllaSeconda)

Con conseguente risultato: 0, 1, 4, 9

Prova a fare questa cosa: prova a ripetere quello che abbiamo fatto con la lista “listaGenerata” una seconda volta. 

In altre parole: reiterala con un secondo ciclo.

Non puoi, vero?

Questo, perché abbiamo creato un generatore.

Che differenza c’è tra un iterabile e un generatore?

Un elemento iterabile, mantiene in memoria il suo contenuto fino a termine esecuzione del programma.

Un generatore è un elemento che può essere iterato una volta sola e non mantiene i suoi valori in memoria, li genera “al volo”, ovvero “on the fly” in inglese come si suol dire.

Ora che abbiamo capito questa differenza, parliamo finalmente della “yield”

Prendiamo il codice di prima, ma facciamo una funzione:

def creaGeneratore():
	lista=range(4)
	for numero in lista:
		yield numero*numero

E scriviamola con una finestra terminale.

Fatto ciò, creiamo una variabile come segue:

generatore=creaGeneratore() 

Abbiamo appena creato un generatore.

Proviamo a stamparne il contenuto:

print(generatore)

Guarda un po’: ti restituisce un oggetto.

Proviamo a iterare il nostro oggetto appena creato:

for numero in generatore:
	print(numero)

Ci stampa i numeri che ci aspetteremmo, niente di strano no?

Cerchiamo di capire però cosa è successo in tutto ciò.

La prima volta che invochiamo la funzione contenuta nella variabile “generatore” tramite la “print”, non ha eseguito il ciclo for giusto?

Infatti la funzione stessa, il codice al suo interno non è stato eseguito, ma ci ha restituito un oggetto generatore contenuto all’interno della variabile “generatore” stessa.

Se però iteriamo la variabile “generatore” e ne stampiamo il contenuto, et voilà! Eccolo.

Quando eseguiamo il ciclo for per iterare il generatore, viene eseguita la funzione all’interno finché non arriva alla parolina magica “yield” e quindi stampa il primo numero (che è “0” elevato alla seconda).

Che cosa fa “yeld”

Dopodiché, passerà alla seconda iterazione e ci stampa “1”, a seguito gli altri numeri che ci aspettiamo.

Il generatore è considerato “vuoto” quando viene eseguita la funzione finché non si arriva alla riga in cui è scritta la parola “yield”, a quel punto restituisce il primo valore del ciclo for.

Il discorso viene ripetuto, quindi re-iterato ancora finché non termina il ciclo for.

“Tutto questo casino Lorenzo?! Non conviene usare una semplice return?”

Quando usare yield e quando usare return

La yield fa una cosa che la return non fa.

Nell’esempio che abbiamo appena visto, la yield interrompe l’esecuzione della funzione per poi riprenderla quando è necessario, ovvero quando nel ciclo che abbiamo usato per stampare i valori, vogliamo vedere quelli successivi allo “0”.

Se avessimo usato la return, questi sarebbero stati stampati tutti in un colpo e fine del cinema.

Ma c’è una sottilissima differenza tra le due.

Quando usiamo la yield, i valori vengono sì iterati ma l’intera sequenza non viene mantenuta in memoria.

Potrebbero interessarti

Lascia un commento

Questo sito potrebbe fare uso di cookie e siccome l'UE mi obbliga a fartelo presente, eccoti il classico banner dove puoi decidere come gestirli. Accetta Leggi di più