Python 为什么';导入时,t globals是否能像我预期的那样工作?
在文件Python 为什么';导入时,t globals是否能像我预期的那样工作?,python,variables,scope,Python,Variables,Scope,在文件foo.py中,我有以下内容: d = {} d['x'] = 0 x = 0 def foo(): global d global x d['x'] = 1 x = 1 然后在口译员中: >>> from foo import * >>> d['x'] 0 >>> x 0 >>> foo() >>> d['x'] 1 >>> x 0 我预料到:
foo.py
中,我有以下内容:
d = {}
d['x'] = 0
x = 0
def foo():
global d
global x
d['x'] = 1
x = 1
然后在口译员中:
>>> from foo import *
>>> d['x']
0
>>> x
0
>>> foo()
>>> d['x']
1
>>> x
0
我预料到:
>>> x
1
我不明白什么?foo的全局名称空间只导入到当前名称空间一次(当您从foo import*执行
时)。之后,如果更改foo
的名称空间,它将不会反映在当前名称空间中
请注意,您仍然可以更改foo
命名空间中的对象,并查看当前命名空间中的更改。这就是为什么您会在d
中看到更改。您仍然有对位于foo
命名空间中的同一对象d
的引用
但是,当您设置:
x = 1
这将在foo
的命名空间中重新绑定一个新对象,您的foo
模块和导入它的主模块(名为\uuuuu main\uuu
)具有单独的命名空间
下面是发生的情况:
导入foo
设置foo
的全局变量x
以引用整数对象0
此引用作为全局变量x
复制到\uuuuu main\uuuu
中
调用foo.foo()
,它将foo
的全局变量x
设置为引用整数对象1
打印\uuuu main\uuuu
的全局变量x
。因为您从未更改此x
所指的内容,所以它仍然指打印的0
简而言之,将名称导入模块不会在两个模块中的名称之间创建任何类型的绑定。它们最初引用相同的值,但如果一个名称重新绑定到另一个对象,则不一定跟随另一个名称
这就是为什么导入foo
通常是一个更好的主意的一个原因。在\uuu main\uuuu
中明确引用foo.x
是指foo
的全局变量x
,即使名称已更改,也会引用其当前值。因此foo
中引用的“全局变量”实际上是foo.d
和foo.x
,不是\uuuu main\uuuu.d
和\uuuu main\uuuuuuux
(虽然\uuuuu main\uuuuuuu.d
和foo.d
指的是同一个对象),尽管foo.x
现在的值为1,\uuuu main\uuuuuuuux
仍然是0。@chepner——说得很好。谢谢——我一直在尝试自己解决这个问题:)@chepner——如果你把模块名称空间看作字典,把foo import*
中的看作是\uu main\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.update(foo.\uuuuuuuu dict\uuuuuuuuuuuuuuuuu)
就更清楚了。对;这是我从未仔细考虑过的global
关键字的行为。该函数在定义全局命名空间时(在foo.func\u globals
中)保存对该命名空间的引用。我建议99%的时间不要使用globals
。99%的时间我建议不要使用foo import*
中的。所以,你需要同时使用它们的几率下降到0.01%左右。。。(如果我的估计大致正确)。