是的:我知道我们不应该在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
为什么会这样?
答案 0 :(得分:3)
让我们回顾一下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
创建一个从x
初始化为bug
的本地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
>>> from bug import * >>> x, y (0, [0]) >>> foo() >>> x, y (0, [100]) >>>
更新:检查foo
设置的utf8
。
>>> import sys >>> sys.modules['bug'].x 100
答案 1 :(得分:1)
Python中的Globals对于模块是全局的,而不是跨所有模块。如果要使用模块错误中的x
,请通过导入bug
模块来使用它下方。
>>> import bug
>>> bug.x
0
>>> bug.foo()
>>> bug.x
100
>>>
请勿使用from bug import *
。这将创建一个新变量x
,初始化为导入时引用的任何bug.x
。如果你在bug.py文件中指定x = 50,那么在执行如下所示的语句from bug import *
之后你将得到50。
>>> from bug import *
>>> x
50
>>>
此新变量x
不会受到方法foo()
的分配的影响。这是第二次它不会给你变量x的值100的原因。
我试图简化它。希望这会有所帮助:)