
Etichette locali libere in Python
Nel linguaggio Python quando usi una variabile senza averla definita in un particolare ambito (scope), questa etichetta è detta "etichetta libera" (free o unbound) o "non vincolata".
In altre parole, se una variabile non è definita all'interno di una funzione, Python cerca di risolverla cercandola negli ambiti esterni più vicini in cui la funzione è definita.
Questo significa che se la variabile libera è usata all'interno di una funzione che non ha una propria definizione di quella variabile, allora la variabile sarà associata allo scope che la contiene (scope enclosing), che è esterno alla funzione stessa.
Nel cercare lo scope della variabile Python segue la gerarchia a ritroso fino a trovare una definizione per quella variabile o, altrimenti, solleva un errore se non viene trovata nessuna definizione.
Le etichette libere sono assegnate staticamente allo scope enclosing nel momento della definizione della funzione, non quando la funzione è chiamata. Questo significa che Python determina a quale variabile (etichetta) si fa riferimento non durante l'esecuzione del codice, ma quando il codice è letto o interpretato per la prima volta.
Ecco un esempio pratico.
Digita questo script:
var = 'I am defined outside the function'
def foo():
print(var)
foo()
Quando la funzione `foo()` viene chiamata, cerca di stampare il contenuto della variabile `var`.
Non trovando la definizione della variabile `var` nell'ambito locale della funzione, Python la cerca nell'ambito più esterno e la trova.
Quindi, il risultato in output è il seguente:
I am defined outside the function
Anche se `var` non è definita all'interno della funzione `foo`, la funzione può accedervi perché `var` è definita nello scope esterno che include la funzione `foo`.
Viceversa, quando Python trova la definizione dell'etichetta nell'ambito locale, crea una variabile locale.
var = 'I am defined outside the function'
def foo():
var = 'I am defined inside the function'
print(var)
foo()
In questo caso Python stampa il valore della variabile locale.
I am defined inside the function
E' comunque possibile modificare manualmente lo scope di una variabile locale usando l'istruzione nonlocal.
L'istruzione nonlocal
Per modificare l'ambito di una variabile locale puoi usare l'istruzione nonlocal.
nonlocal
L'istruzione `nonlocal` in Python ti permette di dichiarare che una variabile all'interno di una funzione si riferisce a una variabile non locale e non globale, ma che si trova in uno scope annidato.
In altre parole, `nonlocal` permette di modificare una variabile in uno scope enclosing che non sia il global scope.
Ecco un esempio per mostrare come funziona:
def outer_function():
var = "Local in outer_function"
def inner_function():
# Indica che si vuole utilizzare la var dello scope superiore
nonlocal var
var = "Modified by inner_function"
inner_function()
print(var)
outer_function()
Senza l'istruzione `nonlocal`, se provassimo a assegnare un valore a `var` dentro `inner_function`, Python creerebbe una nuova variabile locale `var` nell'ambito di `inner_function`.
Con l'istruzione nonlocal, invece, si modifica l'ambito della variabile `var` in `outer_function`.
Quindi, il risultato finale è il seguente:
Modified by inner_function
In questo caso la funzione `outer_function` è detta enclosing function e il suo scope è
detto enclosing.
In questo modo puoi controllare lo scope di ogni variabile locale trasformandolo in uno scope enclosing.
Ricorda che gli scope enclosing sono definiti solo all'interno delle funzioni.