Zakres (scope) zmiennej to kontekst, w którym jest ona dostępna. W Pythonie istnieją 4 podstawowe zakresy, które można zapamiętać według zasady LEGB:
Słowo kluczowe global pozwala zmieniać zmienną zadeklarowaną na poziomie globalnym wewnątrz funkcji.
def foo(): global my_var my_var = 10 # zmienia zmienną globalną
Bez global wewnątrz funkcji zmienna jest uważana za lokalną, nawet jeśli taka nazwa istnieje w zewnętrznym zakresie.
"Co wypisze poniższy kod?"
x = 10 def func(): x = 20 func() print(x)
Odpowiedź:
Wypisze 10, ponieważ wewnątrz funkcji tworzona jest nowa lokalna zmienna x, a globalna nie jest zmieniana.
Historia
W obsłudze komend bota chcieli przechowywać globalny licznik, ale zapomniano o global:
counter = 0 def increment(): counter += 1 # UnboundLocalError: lokalna zmienna 'counter' odniesiona przed przypisaniem
Błąd wynika z tego, że interpreter uważa, że counter jest zmienną lokalną (ponieważ w trakcie funkcji zachodzi jej przypisanie), a nie globalną.
Historia
W funkcjach zagnieżdżonych zapomniano, że bez słowa kluczowego nonlocal ukryta zmienna tworzy lokalny zakres:
def outer(): x = 0 def inner(): x += 1 # UnboundLocalError, x jest uważane za lokalne w inner
Poprawnie:
def outer(): x = 0 def inner(): nonlocal x x += 1
Historia
Pisałem jednoliniowca:
x = 5 y = (lambda: (x := x + 1))() # SyntaxError w Python < 3.8, lub UnboundLocalError później
Zapomniano o różnicy w zakresie dla wyrażenia i lambda. Nie wszystkie konstrukcje wspierają przypisanie wewnątrz lambda, w zależności od wersji Pythona.