La valutazione pigra (lazy evaluation) è un concetto chiave della programmazione efficiente, in cui i valori vengono calcolati solo quando necessario. Storicamente in Python, tutte le strutture incorporate principali (liste, tuple) erano "drogate": creavano e memorizzavano in anticipo tutti gli elementi. Con l'aumento dei volumi di dati e delle operazioni di elaborazione dei flussi, è emersa la necessità di calcoli pigri.
Problema: i calcoli drogati portano a un utilizzo inefficiente della memoria e del tempo in situazioni in cui è possibile ottenere risultati gradualmente, come nel filtraggio, nella trasformazione di lunghe collezioni o nello streaming di file.
Soluzione: in Python sono stati introdotti molti strumenti per calcoli pigri: generatori, iteratori, così come le funzioni della libreria standard (map, filter, zip, enumerate) e il modulo itertools. Tutti essi restituiscono non collezioni pronte, ma oggetti "pigri" che forniscono il risultato uno alla volta.
Esempio di codice:
result = map(lambda x: x * x, range(100)) # restituirà un generatore-iteratore for y in result: print(y) # i valori vengono calcolati iterando import itertools inf = itertools.count(1) for i in inf: if i > 3: break print(i) # 1, 2, 3
Caratteristiche principali:
Le funzioni map/filter restituiscono sempre una lista in Python3?
No, in Python 3 queste funzioni restituiscono iteratori, non liste. Per ottenere una lista è necessario racchiudere il risultato in list().
x = map(int, ['1', '2']) # <oggetto mappa> list(x) # [1, 2]
È possibile ottenere la lunghezza del risultato di map senza convertirlo in una lista?
No, un iteratore non sa in anticipo quanti elementi contiene finché non passa attraverso tutti. È necessario calcolarlo tramite list(), il che annulla la pigrezza.
La funzione range in Python3 è drogata o pigra?
Pigramente: range crea un "oggetto range" — calcola gli elementi su richiesta, senza memorizzare tutta la sequenza.
Uno script elabora un enorme file CSV, creando una lista di tutte le righe tramite list(open(f)). Il server "muore" a causa della mancanza di memoria con un file di grandi dimensioni.
Vantaggi:
Svantaggi:
Il codice utilizza la valutazione pigra: scorre le righe del file con un iteratore for line in open(f), oppure le elabora tramite map/filter senza creare collezioni intermedie.
Vantaggi:
Svantaggi: