Python Language
Variabler Geltungsbereich und Bindung
Suche…
Syntax
- global a, b, c
- nichtlokal a, b
- x = etwas # bindet x
- (x, y) = etwas # bindet x und y
- x + = etwas # bindet x. Ähnlich für alle anderen "op ="
- del x # bindet x
- für x in etwas: # bindet x
- mit etwas als x: # bindet x
- Ausnahme Ausnahme als Ex: # bindet Ex innerhalb des Blocks
Globale Variablen
In Python werden Variablen innerhalb von Funktionen genau dann als lokal betrachtet, wenn sie auf der linken Seite einer Zuweisungsanweisung oder einem anderen verbindlichen Vorkommen erscheinen. Andernfalls wird eine solche Bindung in umschließenden Funktionen bis zum globalen Umfang nachgeschlagen. Dies gilt auch dann, wenn die Zuweisungsanweisung nie ausgeführt wird.
x = 'Hi'
def read_x():
print(x) # x is just referenced, therefore assumed global
read_x() # prints Hi
def read_y():
print(y) # here y is just referenced, therefore assumed global
read_y() # NameError: global name 'y' is not defined
def read_y():
y = 'Hey' # y appears in an assignment, therefore it's local
print(y) # will find the local y
read_y() # prints Hey
def read_x_local_fail():
if False:
x = 'Hey' # x appears in an assignment, therefore it's local
print(x) # will look for the _local_ z, which is not assigned, and will not be found
read_x_local_fail() # UnboundLocalError: local variable 'x' referenced before assignment
Normalerweise spiegelt eine Zuweisung innerhalb eines Bereichs alle äußeren Variablen desselben Namens:
x = 'Hi'
def change_local_x():
x = 'Bye'
print(x)
change_local_x() # prints Bye
print(x) # prints Hi
Wenn Sie einen Namen global
deklarieren, bedeutet dies, dass für den Rest des Bereichs alle Zuweisungen zu dem Namen auf der obersten Ebene des Moduls erfolgen:
x = 'Hi'
def change_global_x():
global x
x = 'Bye'
print(x)
change_global_x() # prints Bye
print(x) # prints Bye
Das global
Schlüsselwort bedeutet, dass Zuweisungen auf der obersten Ebene des Moduls stattfinden, nicht auf der obersten Ebene des Programms. Andere Module benötigen weiterhin den üblichen gepunkteten Zugriff auf Variablen innerhalb des Moduls.
Zusammenfassend: Um zu wissen, ob eine Variable x
für eine Funktion lokal ist, sollten Sie die gesamte Funktion lesen:
- Wenn Sie
global x
, istx
eine globale Variable - Wenn Sie
nonlocal x
, gehörtx
zu einer einschließenden Funktion und ist weder lokal noch global - Wenn Sie
x = 5
oderfor x in range(3)
oder eine andere Bindung gefunden haben, istx
eine lokale Variable - Ansonsten gehört
x
zu einem einschließenden Bereich (Funktionsbereich, globaler Bereich oder Builtins).
Lokale Variablen
Wenn ein Name an eine Funktion gebunden ist, kann er standardmäßig nur innerhalb der Funktion aufgerufen werden:
def foo():
a = 5
print(a) # ok
print(a) # NameError: name 'a' is not defined
Kontrollfluss - Konstrukte haben keine Auswirkungen auf den Umfang (mit Ausnahme von der except
), aber variable Zugriff, der noch nicht zugewiesen wurde , ist ein Fehler:
def foo():
if True:
a = 5
print(a) # ok
b = 3
def bar():
if False:
b = 5
print(b) # UnboundLocalError: local variable 'b' referenced before assignment
Übliche Bindungsoperationen sind Zuweisungen, for
Schleifen und erweiterte Zuordnungen wie a += 5
Nichtlokale Variablen
Python 3 hat ein neues Schlüsselwort namens nonlocal hinzugefügt. Das nichtlokale Schlüsselwort fügt dem inneren Bereich eine Bereichsüberschreibung hinzu. In PEP 3104 können Sie alles darüber lesen. Dies wird am besten anhand einiger Codebeispiele veranschaulicht. Eines der häufigsten Beispiele ist das Erstellen einer Funktion, die inkrementiert werden kann:
def counter():
num = 0
def incrementer():
num += 1
return num
return incrementer
Wenn Sie versuchen, diesen Code auszuführen, erhalten Sie einen UnboundLocalError, da die num -Variable referenziert wird, bevor sie in der innersten Funktion zugewiesen wird. Fügen wir dem Mix nichtlokal hinzu:
def counter():
num = 0
def incrementer():
nonlocal num
num += 1
return num
return incrementer
c = counter()
c() # = 1
c() # = 2
c() # = 3
Grundsätzlich erlaubt Ihnen nonlocal
das Zuweisen von Variablen in einem äußeren, jedoch nicht in einem globalen Bereich. Sie können also nonlocal
in unserer counter
Funktion verwenden, da sie dann versuchen würde, einen globalen Gültigkeitsbereich zuzuweisen. SyntaxError
Sie es aus und Sie erhalten schnell einen SyntaxError
. Stattdessen müssen Sie nonlocal
in einer verschachtelten Funktion verwenden.
(Beachten Sie, dass die hier vorgestellte Funktionalität besser mit Generatoren implementiert wird.)
Verbindliches Vorkommen
x = 5
x += 7
for x in iterable: pass
Jede der obigen Aussagen ist verbindlich - x
wird an das mit 5
bezeichnete Objekt gebunden. Wenn diese Anweisung in einer Funktion angezeigt wird, ist x
standardmäßig funktionslokal. Eine Liste der Bindeanweisungen finden Sie im Abschnitt "Syntax".
Funktionen überspringen Klassenbereich beim Nachschlagen von Namen
Klassen haben während der Definition einen lokalen Gültigkeitsbereich, aber Funktionen innerhalb der Klasse verwenden diesen Gültigkeitsbereich nicht, wenn Sie nach Namen suchen. Da Lambdas Funktionen sind und Erkenntnisse mit dem Funktionsumfang implementiert werden, kann dies zu überraschendem Verhalten führen.
a = 'global'
class Fred:
a = 'class' # class scope
b = (a for i in range(10)) # function scope
c = [a for i in range(10)] # function scope
d = a # class scope
e = lambda: a # function scope
f = lambda a=a: a # default argument uses class scope
@staticmethod # or @classmethod, or regular instance method
def g(): # function scope
return a
print(Fred.a) # class
print(next(Fred.b)) # global
print(Fred.c[0]) # class in Python 2, global in Python 3
print(Fred.d) # class
print(Fred.e()) # global
print(Fred.f()) # class
print(Fred.g()) # global
Benutzer, die mit der Funktionsweise dieses Bereichs nicht vertraut sind, erwarten möglicherweise eine b
class
von b
, c
und e
.
Ab PEP 227 :
Namen im Klassenbereich sind nicht zugänglich. Namen werden im innersten einschließenden Funktionsumfang aufgelöst. Wenn eine Klassendefinition in einer Kette verschachtelter Bereiche auftritt, überspringt der Auflösungsprozess Klassendefinitionen.
Aus der Python-Dokumentation zu Benennung und Bindung :
Der Umfang der in einem Klassenblock definierten Namen ist auf den Klassenblock beschränkt. Sie erstreckt sich nicht auf die Codeblöcke von Methoden - dies schließt Verständnis und Generatorausdrücke ein, da sie mit einem Funktionsumfang implementiert werden. Dies bedeutet, dass Folgendes fehlschlägt:
class A: a = 42 b = list(a + i for i in range(10))
In diesem Beispiel werden Referenzen dieser Antwort von Martijn Pieters verwendet, die eine detailliertere Analyse dieses Verhaltens enthalten.
Der Befehl del
Dieser Befehl hat mehrere verwandte, aber unterschiedliche Formen.
del v
Wenn v
eine Variable ist, entfernt der Befehl del v
die Variable aus ihrem Gültigkeitsbereich. Zum Beispiel:
x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined
Beachten Sie, dass
del
ein verbindliches Vorkommen ist. Dies bedeutet, dass, wenn nicht ausdrücklich anders angegeben (nonlocal
oderglobal
),del v
v
lokalen Bereich lokal wird. Wenn Siev
in einem äußeren Bereich löschennonlocal v
, verwenden Sienonlocal v
oderglobal v
im gleichen Geltungsbereich derdel v
Anweisung.
In allen folgenden Fällen handelt es sich bei der Absicht eines Befehls um ein Standardverhalten, das jedoch nicht von der Sprache erzwungen wird. Eine Klasse kann so geschrieben werden, dass diese Absicht ungültig wird.
del v.name
Dieser Befehl löst einen Aufruf an v.__delattr__(name)
.
Die Absicht ist , das Attribut zu machen name
nicht verfügbar. Zum Beispiel:
class A:
pass
a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'
del v[item]
Dieser Befehl löst einen Aufruf an v.__delitem__(item)
.
Die Absicht ist, dass das item
nicht in das vom Objekt v
implementierte Mapping gehört. Zum Beispiel:
x = {'a': 1, 'b': 2}
del x['a']
print(x) # out: {'b': 2}
print(x['a']) # error: KeyError: 'a'
del v[a:b]
Dies nennt tatsächlich v.__delslice__(a, b)
.
Die Intention ist der oben beschriebenen ähnlich, jedoch mit Slices - Artikelbereiche statt eines einzelnen Artikels. Zum Beispiel:
x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) # out: [0, 3, 4]
Siehe auch Garbage Collection # Der Befehl del .
Lokaler vs Globaler Geltungsbereich
Was ist lokal und global?
Alle Python-Variabes, auf die an einer bestimmten Stelle im Code zugegriffen werden kann, liegen entweder im lokalen oder im globalen Bereich .
Die Erklärung ist, dass der lokale Bereich alle Variablen umfasst, die in der aktuellen Funktion definiert sind, und der globale Bereich enthält Variablen, die außerhalb der aktuellen Funktion definiert sind.
foo = 1 # global
def func():
bar = 2 # local
print(foo) # prints variable foo from global scope
print(bar) # prints variable bar from local scope
Man kann prüfen, welche Variablen in welchem Umfang sind. Integrierte Funktionen locals()
und globals()
geben den gesamten Gültigkeitsbereich als Wörterbücher zurück.
foo = 1
def func():
bar = 2
print(globals().keys()) # prints all variable names in global scope
print(locals().keys()) # prints all variable names in local scope
Was passiert bei Namenskonflikten?
foo = 1
def func():
foo = 2 # creates a new variable foo in local scope, global foo is not affected
print(foo) # prints 2
# global variable foo still exists, unchanged:
print(globals()['foo']) # prints 1
print(locals()['foo']) # prints 2
Verwenden Sie das Schlüsselwort global
um eine globale Variable zu ändern:
foo = 1
def func():
global foo
foo = 2 # this modifies the global foo, rather than creating a local variable
Der Geltungsbereich ist für den gesamten Körper der Funktion definiert!
Das bedeutet, dass eine Variable für eine Hälfte der Funktion niemals global und danach lokal ist oder umgekehrt.
foo = 1
def func():
# This function has a local variable foo, because it is defined down below.
# So, foo is local from this point. Global foo is hidden.
print(foo) # raises UnboundLocalError, because local foo is not yet initialized
foo = 7
print(foo)
Ebenso das Gegenteil:
foo = 1
def func():
# In this function, foo is a global variable from the begining
foo = 7 # global foo is modified
print(foo) # 7
print(globals()['foo']) # 7
global foo # this could be anywhere within the function
print(foo) # 7
Funktionen innerhalb von Funktionen
In Funktionen können viele Ebenen von Funktionen verschachtelt sein, aber innerhalb einer Funktion gibt es nur einen lokalen Gültigkeitsbereich für diese Funktion und den globalen Gültigkeitsbereich. Es gibt keine Zwischenbereiche.
foo = 1
def f1():
bar = 1
def f2():
baz = 2
# here, foo is a global variable, baz is a local variable
# bar is not in either scope
print(locals().keys()) # ['baz']
print('bar' in locals()) # False
print('bar' in globals()) # False
def f3():
baz = 3
print(bar) # bar from f1 is referenced so it enters local scope of f3 (closure)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
def f4():
bar = 4 # a new local bar which hides bar from local scope of f1
baz = 4
print(bar)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
global
vs. nonlocal
(nur Python 3)
Diese beiden Schlüsselwörter werden verwendet, um auf Variablen zuzugreifen, die für die aktuellen Funktionen nicht lokal sind.
Das global
Schlüsselwort gibt an, dass ein Name als globale Variable behandelt werden soll.
foo = 0 # global foo
def f1():
foo = 1 # a new foo local in f1
def f2():
foo = 2 # a new foo local in f2
def f3():
foo = 3 # a new foo local in f3
print(foo) # 3
foo = 30 # modifies local foo in f3 only
def f4():
global foo
print(foo) # 0
foo = 100 # modifies global foo
nonlocal
(siehe Nichtlokale Variablen ), verfügbar in Python 3, nimmt eine lokale Variable aus einem umschließenden Bereich in den lokalen Bereich der aktuellen Funktion.
Aus der Python-Dokumentation zu nonlocal
:
Die nichtlokale Anweisung bewirkt, dass die aufgelisteten Bezeichner auf zuvor gebundene Variablen im nächsten umgebenden Bereich mit Ausnahme von Globals verweisen.
def f1():
def f2():
foo = 2 # a new foo local in f2
def f3():
nonlocal foo # foo from f2, which is the nearest enclosing scope
print(foo) # 2
foo = 20 # modifies foo from f2!