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%左右。。。(如果我的估计大致正确)。