English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In questo articolo, imparerai cosa sono i closure in Python, come definire i closure e le ragioni per cui si utilizzano i closure.
Prima di comprendere cosa sono i closure, dobbiamo prima comprendere cosa sono le funzioni annidate e le variabili non locali.
在另一个函数内部定义的函数称为嵌套函数。嵌套函数可以访问封闭范围的变量。
La funzione definita all'interno di un'altra funzione si chiama funzione annidata. La funzione annidata può accedere alle variabili del contesto chiuso.In Python, di default, queste variabili non locali sono di sola lettura e dobbiamo dichiararle esplicitamente come variabili non locali (usandoChiave nonlocal
) per poterli modificare.
Cosa succede se l'ultima riga della funzione print_msg() restituisce la funzione printer() invece di chiamarla? Questo significa che la definizione della funzione è come segue. def print_msg(msg): # Questo è la funzione chiusa esterna def printer(): # Questo è la funzione annidata Ecco un esempio di funzione annidata che accede a variabili non locali. printer() # Ora, proviamo a chiamare questa funzione. # Eseguiamo questa funzione
print_msg("Hello")Possiamo vedere che la funzione annidata printer() può accedere ai variabili non locali della funzione chiusa.
Definire la funzione chiusura
Cosa succede se l'ultima riga della funzione print_msg() restituisce la funzione printer() invece di chiamarla? Questo significa che la definizione della funzione è come segue. def print_msg(msg): # Questo è la funzione chiusa esterna def printer(): # Questo è la funzione annidata print(msg) return printer # Questo è cambiato # Ora, proviamo a chiamare questa funzione. # Output: Hello another = print_msg("Hello")
another()
Questo è abbastanza inusuale.La funzione print_msg() è chiamata con una stringa, la funzione restituita da "Hello" è associata aUn altro
Nome. Quando si chiama another(), anche se abbiamo completato l'esecuzione della funzione print_msg(), ricordiamo il messaggio.In Python, questa tecnica di aggiungere alcuni dati ("Hello") al codicechiamatoChiusura.
Anche se la variabile è fuori portata o la funzione stessa è stata eliminata dal namespace corrente, ricorda questo valore nel contesto chiuso.
Prova a eseguire i seguenti comandi nel Python Shell per visualizzare l'output.
>>> del print_msg >>> another() Hello >>> print_msg("Hello") Traceback (chiamata più recente in fondo): ... NameError: il nome 'print_msg' non è definito
Dal precedente esempio, è chiaro che in Python, quando una funzione annidata riferisce a un valore nel suo contesto chiuso, abbiamo una chiusura.
I seguenti punti riassumono le condizioni che devono essere soddisfatte per creare una chiusura in Python.
Dobbiamo avere una funzione annidata (funzione all'interno di una funzione).
La funzione annidata deve riferirsi ai valori definiti nella funzione chiusa.
La funzione chiusa deve restituire la funzione annidata.
Allora, a cosa serve la chiusura?
La chiusura può evitare l'uso di valori globali e fornire una forma di nascondimento dei dati. Può anche fornire una soluzione orientata agli oggetti per il problema.
Quando i metodi implementati in una classe sono pochi (la maggior parte delle volte è un metodo), la chiusura può fornire un'altra soluzione più elegante. Ma quando il numero di attributi e metodi aumenta, è meglio implementare una classe.
Questo è un esempio semplice, in cui la chiusura potrebbe essere più preferibile rispetto alla definizione di una classe e alla creazione di un oggetto.
def make_multiplier_of(n): def multiplier(x): return x * n return multiplier # Moltiplicatore di 3 times3 = make_multiplier_of(3) # Moltiplicatore di 5 times5 = make_multiplier_of(5) # Output: 27 print(times3(9)) # Output: 15 print(times5(3)) # Output: 30 print(times5(times3(2)))
I decoratori di Python ancheÈ stato ampiamente utilizzato il chiusura.
Infine, è meglio notare che è possibile trovare i valori chiusi nella funzione di chiusura.
Tutti gli oggetti di funzione hanno un attributo __closure__, che restituisce una tupla di oggetti cella se è una funzione di chiusura.
>>> make_multiplier_of.__closure__ >>> times3.__closure__ (<cella at 0x0000000002D155B8: oggetto int at 0x000000001E39B6E0>,)
L'oggetto cella ha l'attributo di memorizzazione dei valori chiusi cell_contents.
>>> times3.__closure__[0].cell_contents 3 >>> times5.__closure__[0].cell_contents 5