2010-07-13 21 views
5

Ho una variabile globale Ho chiamato Y_VAL che è inizializzato a un valore di 2.Perché python pensa che questa sia una variabile locale?

Ho quindi una funzione, chiamata f() (per brevità), che utilizza Y_VAL.

def f(): 
    y = Y_VAL 
    Y_VAL += 2 

Tuttavia, quando si cerca di eseguire il mio codice, python dà il messaggio di errore:

UnboundLocalError: local variable 'Y_VAL' referenced before assignment 

Se rimuovo l'ultima riga Y_VAL += 2 funziona benissimo.

Perché python pensa che Y_VAL sia una variabile locale?

+0

possibile duplicato di [Perché non posso impostare una variabile globale in Python?] (Http://stackoverflow.com/questions/1281184/why-cant-i-set-a-global-variable-in-python) – Mark

risposta

14

Ti manca la linea global Y_VAL all'interno della funzione.

Quando Y_VAL si verifica sul lato destro di un compito, non è un problema perché l'ambito locale viene cercato per primo, quindi viene cercato l'ambito globale. Tuttavia, sul lato sinistro, è possibile solo assegnare a un valore globale quando si dichiara esplicitamente global Y_VAL.

Da the docs:

Sarebbe impossibile assegnare a una variabile globale senza globale, anche se variabili libere possono riferirsi a variabili globali senza dichiarazione globale.

+0

Questo comportamento si applica in modo diverso per dict? Ho scoperto che posso dichiarare un dict globale e quindi assegnarlo ad una funzione senza usare 'global' ... potresti conoscere il ragionamento alla base di questo? – VMDX

+0

Hmmm, sembra che abbia la stessa domanda di VMDX. Dato un dizionario globale 'd', sono stato in grado di aggiungerlo/modificarlo senza usare la parola chiave globale. Come mai questo è il caso? lo stesso con gli elenchi – Paul

+0

È possibile modificare il contenuto * all'interno * dell'elenco o del dett. Non è possibile modificare (rebind) il riferimento alla lista/dict. Quindi 'd [2:] = 3' è OK, ma' d + = [3] 'non lo è. – bobince

1

Questo è il modo in cui Python funziona: l'assegnazione lega sempre il nome del lato sinistro nello spazio dei nomi circostante più vicino. All'interno di una funzione, lo spazio dei nomi più vicino è lo spazio dei nomi locale della funzione.

Per assegnare a una variabile globale, è necessario dichiararlo global. Ma evita con ogni mezzo lo global. Le variabili globali sono quasi sempre una cattiva progettazione, e quindi l'uso della parola chiave global è un forte suggerimento, che si stanno commettendo errori di progettazione.

0

Mi sono imbattuto nello stesso problema di te e di tanti altri come te, prima di renderci conto che ha bisogno della dichiarazione globale. Ho quindi deciso di spostare tutto all'orientamento all'oggetto e avere un po 'di mente. Chiamami pazzo ma non mi fido di me stesso con la dichiarazione globale e non è difficile imbattersi in un problema di ambito locale che è un problema di debug.

Quindi consiglierei di raccogliere tutte le variabili "globali" inserendole in una classe all'interno di un init (self) e non solo non dovrete preoccuparvi dell'ambito locale ma avrete il vostro codice molto meglio organizzato. Non è uno scherzo di fortuna che la maggior parte dei programmatori preferisce l'OOP.

Problemi correlati