关于python:全局字典不需要关键字全局来修改它们吗?

Global dictionaries don't need keyword global to modify them?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why is not the keyword global not required in this case?

我想知道为什么我可以在不使用global关键字的情况下更改全局字典?为什么它对其他类型是强制性的?这背后有什么逻辑吗?

例如代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/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)

给出以下结果:

1
2
3
4
5
6
me@pc:~/$ ./globalDict.py
{'key2': 2, 'key1': 1}
{'key2': 2, 'key1': 2}  # Dictionary value has been changed
mod
bar
mod

我希望:

1
2
3
4
5
6
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


原因是这条线

1
stringvar ="bar"

不明确,可能是指全局变量,也可能是创建一个名为stringvar的新局部变量。在这种情况下,python默认假定它是局部变量,除非已经使用了global关键字。

然而,这条线

1
dictvar['key1'] += 1

完全不含糊。它只能引用全局变量dictvar,因为该语句必须已经存在dictvar才能不引发错误。

这不特定于字典-列表也是如此:

1
2
3
4
listvar = ["hello","world"]

def listfoo():
    listvar[0] ="goodbye"

或其他种类的物体:

1
2
3
4
5
6
class MyClass:
    foo = 1
myclassvar = MyClass()

def myclassfoo():
    myclassvar.foo = 2

每当使用变异操作而不是重新绑定操作时,都是这样。


您可以在不使用global关键字的情况下修改任何可变对象。

这在python中是可能的,因为当您想将新对象重新分配给已经在全局范围中使用的变量名或定义新的全局变量时,使用global

但是,对于可变对象,您不需要重新分配任何东西,您只是在适当的地方修改它们,因此Python只需从全局范围加载它们并修改它们。

正如医生所说:

It would be impossible to assign to a global variable without global.

1
2
3
4
5
6
7
8
9
10
11
12
13
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号:

1
2
3
4
5
6
7
8
9
10
11
12
13
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