Python - Closures: Una guida per principianti

Ciao, aspirante programmatore Python! Oggi, intraprenderemo un viaggio avventuroso nel mondo delle closure. Non preoccuparti se non hai mai sentito questo termine prima – alla fine di questo tutorial, non solo capirai cosa siano le closure, ma sarai anche in grado di crearle e usarle nel tuo codice. Allora, immergiamoci!

Python - Closures

Cos'è una Closure?

Immagina di avere una scatola magica che può ricordare cose anche dopo averla chiusa. Questo è essenzialmente cosa è una closure nel programmazione! In Python, una closure è un oggetto funzione che ricorda i valori nello scope circostante anche se non sono presenti in memoria.

Sembra confuso? Spezziamo tutto giù:

  1. È una funzione all'interno di un'altra funzione.
  2. Può accedere alle variabili dalla funzione esterna.
  3. Ricorda queste variabili anche quando la funzione esterna ha terminato l'esecuzione.

Pensa a questo come un modo per creare un piccolo pacchetto di funzionalità che porta i suoi dati privati con sé. Cool, no?

Funzioni nidificate

Prima di immergerci più a fondo nelle closure, parliamo delle funzioni nidificate. Queste sono semplicemente funzioni definite all'interno di altre funzioni. Ecco un esempio semplice:

def funzione_esterna(x):
def funzione_interna(y):
return x + y
return funzione_interna

risultato = funzione_esterna(10)
print(risultato(5))  # Output: 15

In questo esempio, funzione_interna è nidificata all'interno di funzione_esterna. La funzione interna può accedere al parametro x della funzione esterna. Questo è un concetto chiave per comprendere le closure.

Ambito delle variabili

Per capire davvero le closure, dobbiamo comprendere l'ambito delle variabili in Python. Ci sono tre tipi di ambito:

  1. Ambito locale: Variabili definite all'interno di una funzione
  2. Ambito circostante: Variabili nella funzione esterna delle funzioni nidificate
  3. Ambito globale: Variabili definite al livello superiore di un modulo

Ecco un esempio per illustrare:

x = "Sono globale!"  # Ambito globale

def esterna():
y = "Sono dall'esterna!"  # Ambito circostante
def interna():
z = "Sono locale!"  # Ambito locale
print(x, y, z)
interna()

esterna()

Quando esegui questo codice, vedrai tutte e tre le variabili stampate. La funzione interna può accedere alle variabili da tutti e tre gli ambiti!

Creare una Closure

Ora che comprendiamo le funzioni nidificate e l'ambito delle variabili, creiamo una closure. Una closure si verifica quando una funzione nidificata fa riferimento a un valore nel suo ambito circostante. Ecco un esempio:

def moltiplica_per(n):
def moltiplicatore(x):
return x * n
return moltiplicatore

volte_due = moltiplica_per(2)
volte_tre = moltiplica_per(3)

print(volte_due(5))   # Output: 10
print(volte_tre(5)) # Output: 15

In questo esempio, moltiplica_per è la nostra funzione esterna, e moltiplicatore è la nostra funzione interna. La magia avviene quando restituiamo moltiplicatore - ricorda il valore di n anche dopo che moltiplica_per ha terminato l'esecuzione. Questa è una closure!

Spezziamo tutto giù passo per passo:

  1. Definiamo moltiplica_per che prende un parametro n.
  2. All'interno di moltiplica_per, definiamo moltiplicatore che prende un parametro x.
  3. moltiplicatore utilizza sia x (il suo parametro proprio) che n (dalla funzione esterna).
  4. Restituiamo moltiplicatore da moltiplica_per.
  5. Quando chiamiamo moltiplica_per(2), restituisce una funzione che moltiplica sempre il suo input per 2.
  6. Allo stesso modo, moltiplica_per(3) restituisce una funzione che moltiplica sempre il suo input per 3.

Questo è il potere delle closure - possono creare funzioni specializzate al volo!

La parola chiave nonlocal

A volte, potresti voler modificare una variabile dall'ambito circostante all'interno della tua funzione interna. Python fornisce la parola chiave nonlocal per questo scopo. Ecco un esempio:

def contatore():
conto = 0
def incremento():
nonlocal conto
conto += 1
return conto
return incremento

mio_contatore = contatore()
print(mio_contatore())  # Output: 1
print(mio_contatore())  # Output: 2
print(mio_contatore())  # Output: 3

In questo esempio, incremento è una closure che ricorda e modifica la variabile conto dal suo ambito circostante. La parola chiave nonlocal dice a Python che conto non è una variabile locale, ma una dall'ambito circostante.

Uso pratico delle Closure

Le closure non sono solo un trucco cool - hanno applicazioni pratiche! Ecco alcune:

  1. Nascondimento dei dati e incapsulamento
  2. Creazione di fabbriche di funzioni
  3. Implementazione di decoratori

Guardiamo un esempio del mondo reale. Immagina di creare un sistema di sconti per un negozio online:

def crea_ajustatore_di_prezzo(sconto):
def ajusta_prezzo(prezzo):
return prezzo * (1 - sconto)
return ajusta_prezzo

sconto_black_friday = crea_ajustatore_di_prezzo(0.2)  # 20% di sconto
sconto_cyber_monday = crea_ajustatore_di_prezzo(0.15)  # 15% di sconto

prezzo_originale = 100
print(f"Prezzo Black Friday: ${sconto_black_friday(prezzo_originale)}")
print(f"Prezzo Cyber Monday: ${sconto_cyber_monday(prezzo_originale)}")

Questo codice crea diverse funzioni di定价 per diversi eventi di sconto, tutte utilizzando la stessa funzione di base. Questo è il potere delle closure!

Sintesi

Congratulations! Hai appena imparato una delle caratteristiche più avanzate di Python. Ricapitoliamo ciò che abbiamo coperto:

Concetto Descrizione
Closure Una funzione che ricorda i valori nello scope circostante
Funzione nidificata Una funzione definita all'interno di un'altra funzione
Ambito delle variabili La visibilità delle variabili (locale, circostante, globale)
nonlocal Parola chiave per modificare le variabili nell'ambito circostante

Ricorda, come ogni strumento potente, le closure dovrebbero essere utilizzate con giudizio. Sono grandi per certi compiti, ma usarle troppo può rendere il tuo codice più difficile da capire. Pratica, sperimenta, e presto sarai in grado di utilizzare le closure come un professionista Python!

Buon coding, e ricorda - in Python, come nella vita, è quello che c'è dentro (funzione) che conta!

Credits: Image by storyset