programowanieBackend developer

Czym jest zakres (scope) zmiennych w Pythonie i jak działa słowo kluczowe `global`? Podaj przykład z praktyki, gdzie niewłaściwe zrozumienie zakresu prowadzi do błędów.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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:

  • Local (lokalny) - wewnątrz funkcji.
  • Enclosing (otaczający) - wewnątrz funkcji zewnętrznych dla funkcji zagnieżdżonych.
  • Global (globalny) - na poziomie modułu.
  • Built-in (wbudowane nazwy Pythona).

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.

Pytanie z pułapką.

"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.

Przykłady rzeczywistych błędów z powodu nieznajomości subtelności tematu.


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.