2014-07-11 12 views
6

Chociaż byłem wychodzić w Python chatroom, ktoś wpadł i podać następujący wyjątek:W jaki sposób "NameError: zmienna wolna" zmienna ", do której odwołuje się przed przypisaniem w otaczającym zakresie" występuje w prawdziwym kodzie?

NameError: free variable 'var' referenced before assignment in enclosing scope 

Nigdy nie zauważyć, że komunikat o błędzie przed i użytkownik kodu pod warunkiem tylko niewielki fragment, który nie mógł sam spowodowałem błąd, więc poszedłem szukać informacji, a ... nie wydaje się, żeby było dużo. Podczas wyszukiwania użytkownik zgłosił problem rozwiązany jako "problem z odstępem", a następnie opuścił pomieszczenie.

Po odtworzeniu całego kawałka, jakie tylko były w stanie odtworzyć wyjątek z kodem jak ta zabawka:

def multiplier(n): 
    def multiply(x): 
     return x * n 
    del n 
    return multiply 

co daje mi:

>>> triple = multiplier(3) 
>>> triple(5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in multiply 
NameError: free variable 'n' referenced before assignment in enclosing scope 

Wszystko dobrze, ale Ciężko pracuję nad tym, jak ten wyjątek może wystąpić na wolności, biorąc pod uwagę, że mój przykład powyżej jest

  1. Całkiem głupi
  2. mało prawdopodobne przypadkowo

... ale oczywiście nie biorąc pod uwagę raport wspomniałem na początku to pytanie.

Więc - jak może ten konkretny wyjątek występuje w prawdziwym kodzie?

+7

Ktoś niekompetentny pisze ten kod na serio? – iCodez

+0

To był błąd czasu kompilacji w Pythonie 2, wygląda na to, że został zmieniony w Pythonie 3. –

+0

@undefinedisnotafunction: To nie jest błąd czasu kompilacji w Pythonie 2. Nie może być tak, jak kompilator nie robi fantazyjna statyczna analiza przepływu sterowania. – BlackJack

Odpowiedz

5

Pomyśl o bardziej złożonej funkcji, w której n jest związany w zależności od pewnych warunków lub nie. Nie ma potrzeby, aby del omawianą nazwę, ale dzieje się tak również wtedy, gdy kompilator widzi przypisanie, więc nazwa jest lokalna, ale ścieżka kodu nie jest pobierana, a jej nazwa nigdy nie jest przypisana. Kolejny głupi przykład:

def f(): 
    def g(x): 
     return x * n 
    if False: 
     n = 10 
    return g