2010-08-19 13 views
6

Biorąc pod uwagę następujący kod:Python zmienna rozwiązywania

a = 0 
def foo(): 
    # global a 
    a += 1 
foo() 

Po uruchomieniu Python narzeka: UnboundLocalError: zmiennej lokalnej 'a' odwołuje przed cesją

Jednak kiedy jest słownikiem ...

a = {} 
def foo(): 
    a['bar'] = 0 
foo() 

Wszystko działa dobrze ...

Ktoś wie, dlaczego możemy podać a w drugiej części kodu, ale nie pierwszej?

Odpowiedz

2

Różnica polega na tym, że w pierwszym przykładzie jesteś przypisując a który tworzy nową nazwę lokalną a że ukrywa globalny a.

W drugim przykładzie nie wykonuje się przypisania do a, więc używane jest globalne a. To jest objęte documentation.

A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope.

+0

Zastanawiam się, dlaczego zdecydowali się opisać to jako "specjalne dziwactwo"? Porównaj z javascript gdzie 'a = 1' automatycznie przypisuje globalny zasięg! Jedyną dobrą rzeczą jest to, że szybko rozpoznajesz kod śmieci przez nieobecności 'var a = 1' – aaronasterling

1

Pytanie dotyczy aktualizacji. Nie można zaktualizować . Operacja przypisania aktualizacji na miejscu nie zaktualizuje się na miejsce a.

Co ciekawe, a = a + 1 również nie działa.

Python generuje lekko zoptymalizowany kod dla tego rodzaju instrukcji. Używa instrukcji "LOAD_FAST".

2   0 LOAD_FAST    0 (a) 
       3 LOAD_CONST    1 (1) 
       6 INPLACE_ADD   
       7 STORE_FAST    0 (a) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   

pamiętać, że korzystanie z a na lewej i prawej stronie znaku równości prowadzi do tej optymalizacji.

Można jednak uzyskać dostęp do a, ponieważ Python wyszukuje dla Ciebie lokalne i globalne przestrzenie nazw.

Ponieważ a nie pojawia się po lewej stronie instrukcji przypisania, używany jest inny rodzaj dostępu, "LOAD_GLOBAL".

2   0 LOAD_CONST    1 (0) 
       3 LOAD_GLOBAL    0 (a) 
       6 LOAD_CONST    2 ('bar') 
       9 STORE_SUBSCR   
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   
0

a += 1 odpowiada a = a + 1. Przypisując zmiennej a, staje się ona lokalna. Wartość, którą próbujesz przypisać a + 1, nie powiodła się, ponieważ a nie została jeszcze powiązana.

0

To bardzo wspólny Python haczyka: jeśli przypisać do zmiennej wewnątrz funkcji (jak to zrobić, z +=), nigdzie w ogóle (nie koniecznie przed użyciem go w inny sposób), nie robi użyj globalnego. Ponieważ jednak to, co robisz, jest efektywne "a = a + 1", próbujesz uzyskać dostęp do a (po prawej stronie wyrażenia) przed przypisaniem do niego.

Spróbuj użyć global a na początku swojej funkcji (ale uważaj, aby nadpisać globalną wartość a).

W drugim przykładzie nie przypisujesz zmiennej a, ale tylko do jednej z jej pozycji. Użyto więc globalnego dyktafonu a.

Powiązane problemy