可能性のある複製:
この場合、キーワードglobalは必要ないのはなぜですか
global
キーワードなしでグローバル辞書を変更できるのはなぜですか?他のタイプに必須なのはなぜですか?この背後に何らかのロジックがありますか?
例えば。コード:
#!/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)
次の結果が得られます。
me@pc:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 2} # Dictionary value has been changed
mod
bar
mod
私が期待するところ:
me@pc:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 1} # I didn't use global, so dictionary remains the same
mod
bar
mod
その理由は、
stringvar = "bar"
あいまいで、グローバル変数を参照している可能性がありますまたはstringvar
という新しいローカル変数を作成している可能性があります。この場合、Pythonは、global
キーワードが既に使用されていない限り、デフォルトでローカル変数であると想定します。
ただし、行
dictvar['key1'] += 1
完全に明確です。ステートメントがエラーをスローしないためには、dictvar
がすでに存在している必要があるため、グローバル変数dictvar
のみを参照できます。
これは辞書に固有のものではありません。リストにも同じことが言えます。
listvar = ["hello", "world"]
def listfoo():
listvar[0] = "goodbye"
または他の種類のオブジェクト:
class MyClass:
foo = 1
myclassvar = MyClass()
def myclassfoo():
myclassvar.foo = 2
再バインド操作ではなく、変更操作が使用される の場合は常にtrueです。
global
キーワードを使用せずに、任意の可変オブジェクトを変更できます。
これはPythonで可能です。なぜなら、global
は、グローバルスコープで既に使用されている変数名に新しいオブジェクトを再割り当てしたり、新しいグローバル変数を定義するために使用されるためです。
しかし、変更可能なオブジェクトの場合、何も再割り当てするのではなく、インプレースで変更するだけなので、Pythonは単にグローバルスコープからそれらをロードして変更します。
As docs say:
グローバルなしでグローバル変数に割り当てることは不可能です。
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