Mögliches Duplikat:
Warum ist das Schlüsselwort global in diesem Fall nicht erforderlich?
Ich frage mich, warum ich das globale Wörterbuch ohne das Schlüsselwort global
ändern kann. Warum ist es für andere Typen obligatorisch? Gibt es eine Logik dahinter?
Z.B. Code:
#!/usr/bin/env python3
stringvar = "mod"
dictvar = {'key1': 1,
'key2': 2}
def foo():
dictvar['key1'] += 1
def bar():
stringvar = "bar"
print(stringvar)
print(dictvar)
foo()
print(dictvar)
print(stringvar)
bar()
print(stringvar)
Gibt folgende Ergebnisse:
[email protected]:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 2} # Dictionary value has been changed
mod
bar
mod
wo ich erwarten würde:
[email protected]:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 1} # I didn't use global, so dictionary remains the same
mod
bar
mod
Der Grund ist, dass die Linie
stringvar = "bar"
ist nicht eindeutig, es könnte sich auf eine globale Variable beziehen, oder es könnte eine neue lokale Variable mit dem Namen stringvar
erstellen. In diesem Fall wird bei Python standardmäßig davon ausgegangen, dass es sich um eine lokale Variable handelt, es sei denn, das Schlüsselwort global
wurde bereits verwendet.
Allerdings ist die Leitung
dictvar['key1'] += 1
Ist völlig eindeutig. Es kann sich nur auf die globale Variable dictvar
beziehen, da dictvar
bereits vorhanden sein muss, damit die Anweisung keinen Fehler auslöst.
Dies gilt nicht nur für Wörterbücher, sondern auch für Listen:
listvar = ["hello", "world"]
def listfoo():
listvar[0] = "goodbye"
oder andere Arten von Objekten:
class MyClass:
foo = 1
myclassvar = MyClass()
def myclassfoo():
myclassvar.foo = 2
Dies ist immer dann der Fall, wenn eine Mutationsoperation anstelle einer erneuten Bindung verwendet wird .
Sie können jedes veränderbare Objekt ändern, ohne das Schlüsselwort global
zu verwenden.
Dies ist in Python möglich, da global
verwendet wird, wenn Sie neuen Objekten Variablennamen zuweisen möchten, die bereits im globalen Bereich verwendet werden, oder um neue globale Variablen zu definieren.
Wenn Sie jedoch keine veränderbaren Objekte neu zuweisen, ändern Sie sie nur direkt. Daher lädt Python sie einfach aus dem globalen Bereich und ändert sie.
Als docs sag:
Ohne global wäre es unmöglich, eine globale Variable zuzuweisen.
In [101]: dic = {}
In [102]: lis = []
In [103]: def func():
dic['a'] = 'foo'
lis.append('foo') # but fails for lis += ['something']
.....:
In [104]: func()
In [105]: dic, lis
Out[105]: ({'a': 'foo'}, ['foo'])
dis.dis
:
In [121]: dis.dis(func)
2 0 LOAD_CONST 1 ('foo')
3 LOAD_GLOBAL 0 (dic) # the global object dic is loaded
6 LOAD_CONST 2 ('a')
9 STORE_SUBSCR # modify the same object
3 10 LOAD_GLOBAL 1 (lis) # the global object lis is loaded
13 LOAD_ATTR 2 (append)
16 LOAD_CONST 1 ('foo')
19 CALL_FUNCTION 1
22 POP_TOP
23 LOAD_CONST 0 (None)
26 RETURN_VALUE