web-dev-qa-db-ger.com

Warum funktioniert das Zuweisen zu meinen globalen Variablen in Python nicht?

Ich habe schreckliche Schwierigkeiten, die Python-Scoping-Regeln zu verstehen.

Mit folgendem Skript:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Gibt die unerwartete (für mich) Ausgabe von:

 Vor setA 
 Der Wert von a ist 7 
 In setA ist a jetzt 42 
 Nach setA 
 Der Wert von a ist 7 

Wo würde ich erwarten, dass der letzte Ausdruck des Wertes von a 42 ist, nicht 7. Was fehlt mir bei den Gültigkeitsregeln für Python für den Gültigkeitsbereich globaler Variablen?

57
Free Wildebeest

Globale Variablen sind speziell. Wenn Sie versuchen, eine Variable a = value innerhalb einer Funktion zuzuweisen, wird eine neue lokale Variable innerhalb der Funktion erstellt, auch wenn eine globale Variable mit demselben Namen vorhanden ist. Um stattdessen auf die globale Variable zuzugreifen, fügen Sie eine global-Anweisung in die Funktion ein:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

Siehe auch Benennung und Bindung für eine detaillierte Erklärung der Python-Regeln für Benennung und Bindung.

110
Adam Rosenfield

Der Trick, um dies zu verstehen, besteht darin, dass Sie eine Variable bei der Zuweisung einer Variablen auch als lokale Variable deklarieren. Statt den Wert der globalen Variablen a zu ändern, setzt setA (value) eine lokale Variable (die als a bezeichnet wird) tatsächlich auf den übergebenen Wert.

Dies wird deutlicher, wenn Sie versuchen, den Wert von a am Anfang von setA (value) wie folgt auszudrucken:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

Wenn Sie versuchen, diesen Python auszuführen, erhalten Sie eine hilfreiche Fehlermeldung:

 Traceback (letzter Anruf zuletzt): 
 Datei "scopeTest.py", Zeile 14 in 
 setA (42) 
 Datei "scopeTest.py", Zeile 7 in setA 
 print "Vor der Zuweisung ist a% d"% (a) 
 UnboundLocalError: Lokale Variable 'a' vor der Zuweisung referenziert 

Dies sagt uns, dass Python entschieden hat, dass die Funktion setA (value) eine lokale Variable namens a hat, die Sie ändern, wenn Sie sie in der Funktion zuweisen. Wenn Sie in der Funktion keine Zuordnung vornehmen (wie bei printA ()), verwendet Python die globale Variable A.

Um eine Variable als global zu kennzeichnen, müssen Sie in Python das globale Schlüsselwort in dem Bereich verwenden, in dem Sie die globale Variable verwenden möchten. In diesem Fall liegt das innerhalb der Funktion setA (value). Das Skript wird also zu:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Dieser einzeilige Zusatz teilt Python mit, dass Sie bei Verwendung der Variablen a in der Funktion setA (value) von der globalen Variablen und nicht von einer lokalen Variablen sprechen.

12
Free Wildebeest

Python hat kein Konzept von Variablen wie andere Sprachen. Sie haben Objekte, die sich "irgendwo" befinden, und Sie haben Verweise auf diese Objekte. = wird verwendet, um diese Objekte Referenzen im Namespace current zuzuweisen.

Sie legen im Namensraum der Funktion setA einen Namen a an, der sich auf das Objekt bezieht, auf das sich der Wert bezieht.

1
DasIch

innerhalb der Funktion wird a als lokale Variable behandelt, die Sie definieren müssen 

global a 

innerhalb der Funktion

1
appusajeev

Die Ausführung einer Funktion führt eine neue Symboltabelle ein, die für die lokalen Variablen der Funktion verwendet wird. Genauer gesagt, alle Variablenzuweisungen in einer Funktion speichern den Wert in der lokalen Symboltabelle. Während Verweise auf Variablen zunächst in die lokale Symboltabelle schauen, dann in die lokalen Symboltabellen der umgebenden Funktionen, dann in die globale Symboltabelle und schließlich in die Tabelle der eingebauten Namen. Daher kann globalen Variablen nicht direkt ein Wert innerhalb einer Funktion zugewiesen werden (es sei denn, sie werden in einer globalen Anweisung benannt), obwohl sie referenziert werden können.

0
Nilesh Jain