Es gab keine gründliche Antwort bezüglich der Python3-Zeit, daher habe ich hier eine Antwort gegeben. Das meiste, was hier beschrieben wird, ist in der 4.2.2 Auflösung der Namen der Python 3-Dokumentation beschrieben.
Wie in anderen Antworten angegeben, gibt es 4 grundlegende Bereiche, den LEGB, für Local, Enclosing, Global und Builtin. Zusätzlich zu diesen gibt es einen speziellen Bereich, den Klassenkörper , der keinen umschließenden Bereich für innerhalb der Klasse definierte Methoden umfasst. Durch Zuweisungen innerhalb des Klassenkörpers wird die Variable von da an im Klassenkörper gebunden.
Insbesondere erstellt keine Blockanweisung außer def
und class
einen variablen Bereich. In Python 2 erstellt ein Listenverständnis keinen Variablenbereich. In Python 3 wird jedoch die Schleifenvariable innerhalb des Listenverständnisses in einem neuen Bereich erstellt.
Die Besonderheiten des Klassenkörpers demonstrieren
x = 0
class X(object):
y = x
x = x + 1 # x is now a variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, the global x
print(y) # -> NameError: global name 'y' is not defined
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
Im Gegensatz zum Funktionskörper können Sie die Variable daher im Klassenkörper demselben Namen zuweisen, um eine Klassenvariable mit demselben Namen zu erhalten. Weitere Suchvorgänge für diesen Namen werden stattdessen in die Klassenvariable aufgelöst.
Eine der größeren Überraschungen für viele Python-Neulinge ist, dass eine for
Schleife keinen variablen Bereich erstellt. In Python 2 erstellen die Listenverständnisse auch keinen Bereich (während Generatoren und Diktverständnisse dies tun!). Stattdessen verlieren sie den Wert in der Funktion oder im globalen Bereich:
>>> [ i for i in range(5) ]
>>> i
4
Das Verständnis kann als gerissene (oder schreckliche, wenn Sie so wollen) Methode verwendet werden, um modifizierbare Variablen in Lambda-Ausdrücken in Python 2 zu erstellen. Ein Lambda-Ausdruck erstellt einen Variablenbereich, wie es die def
Anweisung tun würde, aber in Lambda sind keine Anweisungen zulässig. Zuweisung als Anweisung in Python bedeutet, dass keine Variablenzuweisungen in Lambda zulässig sind, aber ein Listenverständnis ein Ausdruck ist ...
Dieses Verhalten wurde in Python 3 behoben - keine Verständnisausdrücke oder Generatoren lecken Variablen.
Das Globale bedeutet wirklich den Modulumfang; Das Hauptmodul von Python ist das __main__
; Auf alle importierten Module kann über die sys.modules
Variable zugegriffen werden. um Zugang zu erhalten __main__
, kann man verwenden sys.modules['__main__']
, oder import __main__
; Es ist durchaus akzeptabel, dort auf Attribute zuzugreifen und diese zuzuweisen. Sie werden als Variablen im globalen Bereich des Hauptmoduls angezeigt.
Wenn ein Name jemals im aktuellen Bereich zugewiesen wird (außer im Klassenbereich), wird er als zu diesem Bereich gehörend betrachtet, andernfalls wird er als zu einem umschließenden Bereich gehörend betrachtet, der der Variablen zugewiesen wird (möglicherweise wird er nicht zugewiesen noch oder gar nicht) oder schließlich den globalen Geltungsbereich. Wenn die Variable als lokal betrachtet wird, aber noch nicht festgelegt ist oder gelöscht wurde, führt das Lesen des Variablenwerts zu UnboundLocalError
einer Unterklasse von NameError
.
x = 5
def foobar():
print(x) # causes UnboundLocalError!
x += 1 # because assignment here makes x a local variable within the function
# call the function
foobar()
Der Bereich kann deklarieren, dass er die globale Variable (Modulbereich) explizit mit dem globalen Schlüsselwort ändern möchte:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Dies ist auch dann möglich, wenn es im umschließenden Bereich beschattet wurde:
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sees the global value
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
In Python 2 gibt es keine einfache Möglichkeit, den Wert im umschließenden Bereich zu ändern. In der Regel wird dies durch einen veränderlichen Wert simuliert, z. B. 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 nonlocal
kommt das jedoch 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() # identical behavior to the previous example.
Die nonlocal
Dokumentation sagt das
In einer nichtlokalen Anweisung aufgeführte Namen müssen sich im Gegensatz zu den in einer globalen Anweisung aufgeführten Namen auf bereits vorhandene Bindungen in einem umschließenden Bereich beziehen (der Bereich, in dem eine neue Bindung erstellt werden soll, kann nicht eindeutig bestimmt werden).
dh nonlocal
bezieht sich immer auf den innersten äußeren nicht globalen Bereich, an den der Name gebunden wurde (dh zugewiesen, einschließlich als for
Zielvariable, in der with
Klausel oder als Funktionsparameter verwendet).
Jede Variable, die nicht als lokal für den aktuellen Bereich oder einen umschließenden Bereich angesehen wird, ist eine globale Variable. Ein globaler Name wird im globalen Wörterbuch des Moduls nachgeschlagen. Wenn es nicht gefunden wird, wird das Global vom eingebauten Modul nachgeschlagen. Der Name des Moduls wurde von Python 2 in Python 3 geändert. in Python 2 war es __builtin__
und in Python 3 heißt es jetzt builtins
. Wenn Sie einem Attribut des eingebauten Moduls zuweisen, wird es anschließend für jedes Modul als lesbare globale Variable angezeigt, es sei denn, dieses Modul schattiert sie mit einer eigenen globalen Variablen mit demselben Namen.
Das Lesen des eingebauten Moduls kann ebenfalls nützlich sein. Angenommen, Sie möchten die Druckfunktion im Python 3-Stil in einigen Teilen der Datei verwenden, in anderen Teilen der Datei wird die print
Anweisung jedoch weiterhin verwendet . In Python 2.6-2.7 können Sie die Python 3- print
Funktion mit folgenden Funktionen abrufen :
import __builtin__
print3 = __builtin__.__dict__['print']
Das from __future__ import print_function
importiert die print
Funktion eigentlich nirgendwo in Python 2 - stattdessen deaktiviert es nur die Parsing-Regeln für print
Anweisungen im aktuellen Modul, behandelt sie print
wie jede andere Variablenkennung und ermöglicht so print
das Nachschlagen der Funktion in den integrierten Funktionen.