2014-07-11 8 views
6

Mentre ero in giro nel Python chatroom, qualcuno è sceso in e segnalato la seguente eccezione:In che modo "NameError: la variabile libera" var "a cui si fa riferimento prima dell'assegnazione nel campo di applicazione" si verifica nel codice reale?

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

non avevo mai visto che il messaggio di errore, prima, e l'utente fornito solo un piccolo frammento di codice che non poteva ho causato l'errore da solo, quindi sono andato su Google a cercare informazioni e ... sembra che non ci sia molto. Durante la ricerca, l'utente ha segnalato il problema risolto come "problema di spazio bianco", quindi ha lasciato la stanza.

Dopo aver giocato un po 'intorno, sono stato in grado di riprodurre l'eccezione con il codice di giocattolo come questo solo:

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

che mi dà:

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

Tutto bene, ma Sto avendo difficoltà a capire come questa eccezione potrebbe verificarsi in natura, dato che il mio esempio sopra è

  1. Abbastanza stupido
  2. improbabile che ciò accada per caso

... ma ovviamente lo fa, dato il rapporto che ho citato all'inizio di questa domanda.

Così - come può questa eccezione specifica si verifica nel codice reale?

+7

Qualcuno incompetente scrive quel codice per davvero? – iCodez

+0

Questo errore di compilazione in Python 2 sembra essere cambiato in Python 3. –

+0

@undefinedisnotafunction: Non è un errore di compilazione in Python 2. Non può essere come il compilatore non lo fa fantasia analisi statica del flusso di controllo. – BlackJack

risposta

5

Pensa a una funzione più complessa in cui n è associato in base a qualche condizione, oppure no. Non è necessario del il nome in questione, ma succede anche se il compilatore vede un'assegnazione, quindi il nome è locale, ma il percorso del codice non viene preso e il nome non viene mai assegnato. Un altro esempio stupido:

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