L'ambito (scope) di una variabile è il contesto in cui è accessibile. In Python ci sono 4 ambiti principali, che puoi ricordare con il principio LEGB:
La parola chiave global consente di modificare una variabile dichiarata a livello globale dall'interno di una funzione.
def foo(): global my_var my_var = 10 # modifica la variabile globale
Senza global, all'interno della funzione la variabile è considerata locale, anche se esiste un nome simile nell'ambito esterno.
"Cosa stamperà il seguente codice?"
x = 10 def func(): x = 20 func() print(x)
Risposta:
Stamperà 10, perché all'interno della funzione viene creata una nuova variabile locale x, la globale non viene modificata.
Storia
Nel gestore comandi di un bot volevano mantenere un contatore globale, ma hanno dimenticato il global:
counter = 0 def increment(): counter += 1 # UnboundLocalError: variabile locale 'counter' referenziata prima dell'assegnazione
Errore causato dal fatto che l'interprete considera counter una variabile locale (poiché all'interno della funzione c'è un'assegnazione), e non globale.
Storia
Nelle funzioni annidate hanno dimenticato che senza la parola chiave nonlocal una variabile nascosta crea un ambito locale:
def outer(): x = 0 def inner(): x += 1 # UnboundLocalError, x è considerato locale in inner
Corretto:
def outer(): x = 0 def inner(): nonlocal x x += 1
Storia
Hanno scritto una riga:
x = 5 y = (lambda: (x := x + 1))() # SyntaxError in Python < 3.8, o UnboundLocalError più tardi
Hanno dimenticato la differenza di ambito tra un'espressione e una lambda. Non tutte le costruzioni supportano l'assegnazione all'interno di una lambda, a seconda della versione di Python.