Es gab keine gründliche Antwort bezüglich Python3-Zeit, also habe ich hier eine Antwort gemacht. Das meiste, was hier beschrieben wird, ist im 4.2.2 Auflösung von Namen der Python 3-Dokumentation detailliert beschrieben.
Wie in anderen Antworten angegeben, gibt es 4 grundlegende Bereiche, die LEGB, für Lokal, Schließende, Globale und Eingebaute. Zusätzlich dazu existiert ein spezieller Bereich, der Klassenbereich, der keinen umschließenden Bereich für Methoden definiert, die innerhalb der Klasse definiert wurden; jegliche Zuweisungen innerhalb des Klassenbereichs lassen die Variable von nun an im Klassenbereich gebunden sein.
Insbesondere erstellt keine Blockanweisung außer def
und class
einen Variablenspeicher. In Python 2 erstellt eine Listenverständlichkeit keinen Variablenspeicher, jedoch wird in Python 3 die Schleifenvariable innerhalb von Listenverständnissen in einem neuen Bereich erstellt.
Um die Besonderheiten des Klassenbereichs zu demonstrieren
x = 0
class X(object):
y = x
x = x + 1 # x ist jetzt eine Variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, das globale x
print(y) # -> NameError: globaler Name 'y' ist nicht definiert
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
So können im Klassenbereich im Gegensatz zum Funktionsbereich die Variable mit demselben Namen erneut zugewiesen werden, um eine Klassenvariable mit demselben Namen zu erhalten; weitere Nachschlagen dieses Namens lösen auf die Klassenvariable.
Eine der größten Überraschungen für viele Neueinsteiger in Python ist, dass eine for
-Schleife keinen Variablenspeicher erstellt. In Python 2 erstellen auch Listenverständnisse keinen Bereich (während Generatoren und Dictionary-Verständnisse dies tun!) Stattdessen geben sie den Wert in den Funktions- oder globalen Bereich frei:
>>> [ i for i in range(5) ]
>>> i
4
Die Verständnisse können als raffinierter (oder schrecklicher, wenn Sie so wollen) Weg verwendet werden, um modifizierbare Variablen innerhalb von Lambda-Ausdrücken in Python 2 zu erstellen - ein Lambda-Ausdruck erstellt einen Variablenspeicher, wie die def
-Anweisung, allerdings sind in Lambda keine Anweisungen erlaubt. Da Zuweisung in Python eine Anweisung ist, bedeutet dies, dass keine Variablenzuweisungen in Lambda erlaubt sind, jedoch ein Listenverständnis ein Ausdruck ist...
Dieses Verhalten wurde in Python 3 behoben - keine Verständnisausdrücke oder Generatoren geben Variablen frei.
Global bedeutet wirklich der Modulbereich; das Haupt-Python-Modul ist das __main__
; alle importierten Module sind über die Variable sys.modules
zugänglich; um auf __main__
zuzugreifen, kann man sys.modules['__main__']
verwenden oder import __main__
; es ist vollkommen akzeptabel, Attribute dort abzurufen und zuzuweisen; sie erscheinen als Variablen im globalen Bereich des Hauptmoduls.
Wenn ein Name jemals im aktuellen Bereich zugewiesen wird (außer im Klassenbereich), wird er als zu diesem Bereich gehörend betrachtet, ansonsten wird davon ausgegangen, dass er zu einem umschließenden Bereich gehört, der der Variable Zuweisungen zuweist (es kann sein, dass diese noch nicht zugewiesen wurde oder überhaupt nicht), oder schließlich zum globalen Bereich. Wenn die Variable als lokal betrachtet wird, aber noch nicht festgelegt wurde oder gelöscht wurde, führt das Lesen des Variablenwerts zu UnboundLocalError
, was eine Unterklasse von NameError
ist.
x = 5
def foobar():
print(x) # führt zu UnboundLocalError!
x += 1 # da Zuweisung hier x zu einer lokalen Variable innerhalb der Funktion macht
# Funktion aufrufen
foobar()
Der Bereich kann explizit angeben, dass er die globale (Modulbereich) Variable ändern möchte, mit dem globalen Schlüsselwort:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Dies ist auch möglich, wenn sie im umgebenden Bereich überlagert wurde:
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sieht den globalen Wert
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
In Python-2 gibt es keinen einfachen Weg, den Wert im umgebenden Bereich zu ändern; normalerweise wird dies simuliert, indem ein veränderlicher Wert verwendet wird, wie eine Liste mit einer Länge von 1:
def make_closure():
value = [0]
def get_next_value():
value[0] += 1
return value[0]
return get_next_value
get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2
In Python 3 kommt jedoch nonlocal
zur Rettung:
def make_closure():
value = 0
def get_next_value():
nonlocal value
value += 1
return value
return get_next_value
get_next = make_closure() # identisches Verhalten wie im vorherigen Beispiel.
Die nonlocal
-Dokumentation besagt, dass
Namen, die in einer nonlocal-Anweisung aufgeführt sind, im Gegensatz zu denen, die in einer globalen Anweisung aufgeführt sind, müssen sich auf bereits bestehende Bindungen in einem umschließenden Bereich beziehen (der Bereich, in dem eine neue Bindung erstellt werden sollte, kann nicht eindeutig bestimmt werden).
d.h. nonlocal
bezieht sich immer auf den am engsten umgebenen äußeren nicht-globalen Bereich, in dem der Name gebunden wurde (d.h. zugewiesen wurde, einschließlich Verwendung als Zielvariable von for
, in der with
-Klausel oder als Funktionsparameter).
Jede Variable, die nicht als lokal für den aktuellen Bereich oder einen umgebenden Bereich angesehen wird, ist eine globale Variable. Ein globaler Name wird im globalen Wörterbuch des Moduls gesucht; wenn nicht gefunden, wird der globale Name dann aus dem builtins-Modul gesucht; der Name des Moduls wurde von Python 2 auf Python 3 geändert; in Python 2 war es __builtin__
und in Python 3 heißt es jetzt builtins
. Wenn Sie ein Attribut des builtins-Moduls zuweisen, ist es danach für jedes Modul als lesbarer globaler Schreibzugriff sichtbar, es sei denn, das Modul überschattet sie mit seinem eigenen globalen Namen mit demselben Namen.
Das Lesen des builtins-Moduls kann auch nützlich sein; nehmen wir an, Sie wollen die Python 3-Stil-Print-Funktion in einigen Teilen der Datei verwenden, während andere Teile der Datei immer noch die print
-Anweisung verwenden. In Python 2.6-2.7 können Sie die Python 3 print
-Funktion erhalten mit:
import __builtin__
print3 = __builtin__.__dict__['print']
Das from __future__ import print_function
importiert tatsächlich die print
-Funktion nirgendwo in Python 2 - stattdessen deaktiviert es lediglich die Parsing-Regeln für die print
-Anweisung im aktuellen Modul, behandelt print
wie jeden anderen Variablennamen und erlaubt damit, dass die print
-Funktion im builtins-Modul aufgerufen wird.
4 Stimmen
Die Geltungsbereichsregeln werden ziemlich knapp, aber auch vollständig, in der Python-Dokumentation beschrieben: docs.python.org/3/reference/….