Frage

Ich habe schreckliche Mühe versuchen, Python Scoping-Regeln zu verstehen.

Mit dem folgende 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 das Unerwartete (für mich) Ausgang:

    Before setA
    Value of a is 7
    Inside setA, a is now 42
    After setA
    Value of a is 7

Wo ich wäre der letzte Druck des Wertes eines erwarte 42 zu sein, nicht 7. Was ich für das Scoping von globalen Variablen über Pythons Bereichsregeln bin fehle?

War es hilfreich?

Lösung

Globale Variablen sind etwas Besonderes. Wenn Sie versuchen, innerhalb einer Funktion einer Variablen a = value zuweisen, erstellt es eine neue lokale Variable in der Funktion, auch wenn es eine globale Variable mit dem gleichen Namen. Um stattdessen die globale Variable zuzugreifen, fügen Sie eine global Anweisung innerhalb der Funktion:

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

Siehe auch Naming und Bindung für eine detaillierte Erklärung von Pythons Benennung und verbindliche Regeln.

Andere Tipps

Der Trick, um dies zu verstehen, ist, dass, wenn Sie ein Variablen zuweisen, mit =, Sie es auch als lokalem Variable deklarieren. Anstatt also den Wert der globalen Variablen eine Änderung setA (Wert) setzt eigentlich eine lokale Variable auf den Wert übergeben (das ist ein aufgerufen werden, geschieht).

Dies wird noch deutlicher, wenn Sie versuchen, den Wert eines zu Beginn des setA (Wert) wie so drucken:

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

Wenn Sie versuchen, dieser Python ausführen werden Sie einen hilfreichen Fehler:

Traceback (most recent call last):
  File "scopeTest.py", line 14, in 
    setA(42)
  File "scopeTest.py", line 7, in setA
    print "Before assignment, a is %d" % (a)
UnboundLocalError: local variable 'a' referenced before assignment

Das sagt uns, dass Python hat entschieden, dass die setA (Wert) Funktion eine lokale Variable genannt, das ist, was Sie ändern, wenn Sie es in der Funktion zuweisen. Wenn Sie nicht zuordnen zu einem in der Funktion (wie bei druckenA ()) verwendet dann Python die globale Variable A.

Um eine Variable zu markieren, wie global die globale Schlüsselwort in Python verwenden müssen, in den Rahmen, die Sie die globale Variable verwenden möchten . In diesem Fall, der innerhalb des setA (Wert) Funktion ist. Also das Skript wird:

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

Diese eine Zeile hinaus sagt Python, dass, wenn Sie die Variable a in der setA (Wert) Funktion, die Sie über die globale Variable sprechen, nicht eine lokale Variable.

Python hat kein Konzept von Variablen als anderen Sprachen. Sie haben Objekte, die „irgendwo“ und Sie haben Referenzen auf diese Objekte sind. = Wird verwendet, um diese Objekte zu Referenzen in der Strom Namensraum zuzuweisen.

Sie erstellen einen Namen ein im Namensraum der setA Funktion, die auf das Objekt bezieht sich auf welchen Wert bezieht.

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

  

global a

in der Funktion

Die Ausführung einer Funktion führt eine neue Symboltabelle für die lokalen Variablen der Funktion verwendet. Genauer gesagt, werden alle Variablenzuweisungen in einer Funktion, um den Wert in der lokalen Symboltabelle speichern; während Variablenreferenzen in der lokalen Symboltabelle, dann in den lokalen Symboltabellen der umgebenden Funktionen, dann in der globalen Symboltabelle und schließlich in der Tabelle der eingebauten Namen suchen zuerst. So können globale Variablen nicht direkt einen Wert innerhalb einer Funktion zugeordnet werden (es sei denn, in einer globalen Erklärung genannt), obwohl sie referenziert werden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top