是的:我知道我们不应该在Python中使用全局变量,但我试图理解这种行为。
我有一个名为 bug.py 的文件:
x = 0
def foo():
global x
x = 100
if __name__ == '__main__':
foo()
print(x)
当我将其作为文件执行时,我得到了 100 的预期结果,见下文。
(mani) franz@ubuntu:~/dropboxpython/poolparty$ python bug.py
100
但是,当我在 repl 中做同样的事情时,x 不会变成 100,见下文
(mani) franz@ubuntu:~/dropboxpython/poolparty$ python
Python 3.6.4 | packaged by conda-forge | (default, Dec 23 2017, 16:31:06)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from bug import *
>>> x
0
>>> foo()
>>> x
0
为什么会这样?
让我们回顾一下from module import something
语句的作用:
对该值的引用存储在本地命名空间中,使用 如果存在 as 子句中的名称,否则使用 名字
我还想补充一点,module
已导入(即添加到sys.modules
),但未创建名称module
。
第二个要点是整数是不可变的。不可变对象的行为如下所示,因为每个值都是一个单独的对象:
a = 0 # a-->0
b = a # a-->0<--b
a = 3 # 3<--a 0<--b; new object int(3) is created; b is still 0
因此,令人高兴的是,导入会创建一个本地x
初始化为从零bug
x
。调用foo()
更改x
bug
模块,但如上所示,它不会影响本地x
。
试试这个看看不可变x
和可变y
之间的区别:
x = 0
y = [0]
def foo():
global x, y
x = 100
y[0] = 100
if __name__ == '__main__':
foo()
print(x)
print(y)
从错误导入>>> *>>> x, y (0, [0])>>> foo()>>> x, y (0, [100])>>>
更新:检查foo
设置的x
。
>>>导入系统>>> sys.modules['bug'].x 100
Python 中的全局变量是模块的全局变量,而不是所有模块的全局变量。如果要使用模块错误中的x
,请通过导入bug
模块来使用它,如下所示。
>>> import bug
>>> bug.x
0
>>> bug.foo()
>>> bug.x
100
>>>
不要使用from bug import *
。这将创建一个新变量x
初始化为导入时引用的任何bug.x
。如果您在文件中分配 x=50 bug.py 则在执行如下语句from bug import *
后将获得 50。
>>> from bug import *
>>> x
50
>>>
这个新变量x
不会受到方法foo()
赋值的影响。这就是第二次它不会给你变量 x 的值 100 的原因。
我试图简化它。希望这对:)有所帮助