Python 全局字典不需要关键字 global 来修改它们?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14323817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Global dictionaries don't need keyword global to modify them?
提问by Jovik
I wonder why I can change global dictionary without globalkeyword? Why it's mandatory for other types? Is there any logic behind this?
我想知道为什么我可以在没有global关键字的情况下更改全局字典?为什么它对其他类型是强制性的?这背后有什么逻辑吗?
E.g. 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)
Gives following results:
给出以下结果:
me@pc:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 2} # Dictionary value has been changed
mod
bar
mod
where I would expect:
我期望的地方:
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
采纳答案by David Robinson
The reason is that the line
原因是这条线
stringvar = "bar"
is ambiguous, it could be referring to a global variable, orit could be creating a new local variable called stringvar. In this case, Python defaults to assuming it is a local variable unless the globalkeyword has already been used.
是模棱两可的,它可能指的是一个全局变量,或者它可能正在创建一个名为stringvar. 在这种情况下,除非global已经使用了关键字,否则 Python 默认假设它是一个局部变量。
However, the line
然而,该行
dictvar['key1'] += 1
Is entirely unambiguous. It can be referring only to the global variable dictvar, since dictvarmust already exist for the statement not to throw an error.
是完全不含糊的。它可以只引用全局变量dictvar,因为dictvar语句必须已经存在才能不抛出错误。
This is not specific to dictionaries- the same is true for lists:
这不是特定于字典的 - 列表也是如此:
listvar = ["hello", "world"]
def listfoo():
listvar[0] = "goodbye"
or other kinds of objects:
或其他类型的对象:
class MyClass:
foo = 1
myclassvar = MyClass()
def myclassfoo():
myclassvar.foo = 2
It's true whenever a mutating operation is used rather than a rebinding one.
每当使用变异操作而不是重新绑定操作时都是如此。
回答by Ashwini Chaudhary
You can modify any mutable object without using globalkeyword.
您可以在不使用global关键字的情况下修改任何可变对象。
This is possible in Python because globalis used when you want to reassign new objects to variable names already used in global scope or to define new global variables.
这在 Python 中是可能的,因为global当您想将新对象重新分配给已在全局范围内使用的变量名称或定义新的全局变量时使用。
But in case of mutable objects you're not re-assigning anything, you're just modifying them in-place, therefore Python simply loads them from global scope and modifies them.
但是对于可变对象,您不会重新分配任何内容,您只是在原地修改它们,因此 Python 只需从全局范围加载它们并修改它们。
As docssay:
正如文档所说:
It would be impossible to assign to a global variable without global.
如果没有全局变量,就不可能分配给全局变量。
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:
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

