Come utilizzare i generatori in Python (dichiarazione di rendimento)

Scopri come scrivere generatori in Python. Comprendere la parola chiave yield, la valutazione pigra, l'ottimizzazione della memoria e confrontare i generatori con le strutture degli elenchi.

Prova questa soluzione nell'editor

Panoramica

Quando si lavora con set di dati di grandi dimensioni, file di registro o flussi di dati infiniti, il caricamento simultaneo di tutti gli elementi in memoria (come la restituzione di un elenco di grandi dimensioni) può facilmente esaurire la RAM del sistema e mandare in crash l'applicazione. Python offre una soluzione brillante ed efficiente in termini di memoria: i generatori.

Un generatore è un tipo speciale di funzione che restituisce un iteratore pigro. Invece di calcolare tutti i valori contemporaneamente e restituirli, un generatore produce i valori uno per uno come richiesto. La differenza fondamentale è l'istruzione "yield". Quando una funzione generatrice chiama "yield", mette in pausa il suo stato di esecuzione (variabili, puntatore alle istruzioni) e restituisce il valore restituito. Quando viene richiesto il valore successivo, la funzione riprende esattamente da dove era stata interrotta.

Poiché i calcoli del generatore vengono eseguiti in modo lento, utilizzano quasi zero memoria indipendentemente dalla dimensione del set di dati. Python supporta anche le espressioni del generatore, che utilizzano la sintassi tra parentesi "(x for x in data)" per creare generatori in linea leggeri senza dichiarare funzioni complete.

Codice e output di esecuzione

Questo script dimostra la generazione di sequenze utilizzando le funzioni del generatore con l'istruzione yield e le espressioni del generatore.

generators_demo.py
Prova nell'editor
# 1. Generator function using yield
def count_up_to(limit):
    count = 1
    while count <= limit:
        yield count
        count += 1

# Instantiating the generator
counter = count_up_to(3)
print("Memory safe generator instantiated.")

# Fetching values manually
print("Next 1:", next(counter))
print("Next 2:", next(counter))
print("Next 3:", next(counter))

# 2. Iterating with a for loop (automatically handles StopIteration)
print("\n--- Looping over generator ---")
for num in count_up_to(4):
    print("Num:", num)

# 3. Generator expression (Shorthand syntax)
squares_gen = (x**2 for x in range(1, 4))
print("\nGenerator expression elements:")
print(list(squares_gen)) # Cast to list to print all elements
Uscita terminale
Memory safe generator instantiated.
Next 1: 1
Next 2: 2
Next 3: 3

--- Looping over generator ---
Num: 1
Num: 2
Num: 3
Num: 4

Generator expression elements:
[1, 4, 9]

Implementazione passo dopo passo

  • Definire una funzione utilizzando la parola chiave standard def.
  • Utilizza la parola chiave yield invece di restituire i valori di rendimento al flusso dell'iteratore.
  • Itera sul generatore utilizzando un ciclo for o chiama la funzione next(gen) incorporata per estrarre i valori.
  • Utilizza le espressioni del generatore (utilizzando le parentesi) per conversioni pigre semplici e in linea.

Domande frequenti

Qual è il vantaggio principale dei generatori rispetto alle liste?

Efficienza della memoria. Gli elenchi memorizzano tutti gli elementi nella RAM contemporaneamente, mentre i generatori producono elementi uno per uno su richiesta, consentendoti di elaborare set di dati più grandi della memoria totale del tuo sistema.

Cosa succede quando un generatore esaurisce gli elementi?

Python solleva un'eccezione StopIteration. Un ciclo for rileva automaticamente questa eccezione per uscire dal ciclo con garbo, ma chiamare manualmente next() su un generatore esaurito genererà l'eccezione.

Argomenti correlati

Risorse Python consigliate

Espandi le tue conoscenze con tutorial interattivi, foglietti illustrativi e confronti di codici correlati.