3.1 Introduzione alle chiusure
Una chiusura è una funzione che cattura le variabili dal suo ambiente circostante, anche dopo che quell'ambiente ha terminato la sua esecuzione. Questo significa che una chiusura può "ricordare" i valori delle variabili del suo ambiente esterno e continuare a lavorare con esse anche quando questo ambiente non è più attivo.
Per capire come funzionano le chiusure, diamo un'occhiata al seguente esempio:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # Uscita: 15
Esaminiamo cosa è scritto qui:
Funzione esterna (outer_function)
: Questa funzione accetta
un argomento x
e definisce una funzione interna inner_function
,
che accetta un argomento y
e restituisce la somma di x
e y
. La funzione
inner_function
non viene chiamata all'interno di
outer_function
, ma solo dichiarata.
Funzione interna (inner_function)
: Questa funzione
viene restituita da outer_function
e mantiene al suo interno
un collegamento al valore x
, che è stato passato a outer_function
.
Chiusura: La variabile closure
diventa
una chiusura, che "ricorda" il valore di x
(in questo caso, 10) e può
usarlo quando viene chiamata.
Di solito nessuno riesce a lavorare correttamente con le chiusure al primo tentativo. Quindi proviamo a migliorare la vostra comprensione delle chiusure con degli esempi.
3.2 Esempi di utilizzo delle chiusure
Creazione di una funzione generatore
Le chiusure possono essere utilizzate per creare funzioni generatrici che generano sequenze di valori.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
print(counter()) # Uscita: 1
print(counter()) # Uscita: 2
print(counter()) # Uscita: 3
Spiegazione:
Funzione generatore (make_counter)
: Questa funzione crea
una variabile count
e restituisce la funzione interna counter
, che
incrementa il valore di count
e lo restituisce.
Chiusura: La funzione counter
mantiene lo stato della variabile
count
e può modificarlo ad ogni chiamata.
Creazione di una funzione con configurazione
Le chiusure possono essere utilizzate per creare funzioni con una configurazione predefinita.
def make_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # Uscita: 10
print(triple(5)) # Uscita: 15
Spiegazione:
Funzione configuratore (make_multiplier)
: Questa funzione
accetta un moltiplicatore factor
e restituisce la funzione interna multiplier
,
che moltiplica il valore di input per factor
.
Chiusure: Le funzioni double
e triple
sono chiusure,
che mantengono i loro valori factor
e li utilizzano per la moltiplicazione.
Filtraggio dati con parametri
Le chiusure possono essere utili per creare funzioni di filtro con parametri.
def make_filter(threshold):
def filter_func(value):
return value > threshold
return filter_func
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data) # Uscita: [15, 20]
Spiegazione:
Funzione filtro (make_filter)
: Questa funzione accetta
un valore soglia threshold
e restituisce la funzione interna filter_func
,
che verifica se il valore supera la soglia.
Chiusura: La funzione filter_func
mantiene il valore threshold
e lo utilizza per filtrare i dati.
3.3 Pro e contro delle chiusure
Vantaggi dell'uso delle chiusure
Incapsulamento dello stato: Le chiusure consentono di incapsulare lo stato in una funzione, evitando variabili globali e migliorando la leggibilità e la manutenzione del codice.
Flessibilità: Le chiusure possono essere utilizzate per creare funzioni con una configurazione o comportamento specifico, rendendo il codice più flessibile e adattabile.
Programmazione funzionale: Le chiusure sono un concetto importante nella programmazione funzionale, permettendo di creare funzioni di ordine superiore e altre costruzioni funzionali.
Limitazioni e potenziali problemi
Nonostante i numerosi vantaggi, le chiusure presentano anche alcune limitazioni:
Uso della memoria: Le chiusure possono mantenere riferimenti a oggetti che non sono più utilizzati, il che può portare a perdite di memoria.
Difficoltà di debug: Le chiusure possono rendere più complesso il debug del codice, poiché lo stato delle variabili potrebbe non essere ovvio.
GO TO FULL VERSION