14

我很惊讶地发现

import foo

from foo import *

对全球成员产生了不同的影响。我想确认我的实验是正确的行为。

在第一个示例中,更改模块 foo 中的成员将反映在所有导入 foo 的代码中。但是,在后一种情况下更改该成员似乎只会影响导入它的文件。换句话说,使用后一种方法将为每个导入文件提供其自己的 foo 成员副本。

我想要的行为是从所有文件中访问 foo.x,能够从所有文件中更改它,并将该更改反映在所有文件中(如果你愿意,这是一个真正的全局)。

4

2 回答 2

16

是的,你的观察是正确的。这是绑定在 Python 中工作方式的结果。

当一个人

import foo

然后foo成为引用模块的全局名称foo。当一个人

foo.bar = 7

然后跟随引用并foo加载对象。然后7存储在bar属性中。

当另一个模块导入foo时,它只是将对象拉出sys.modules['foo']并获取修改后的值。

当一个人

from foo import bar

globals()['bar']设置为参考foo.bar。以后做的时候

 bar = 7

globals()['bar']不再引用foo.bar,而是引用7. 也就是说,简单地替换了导入模块全局范围内的原始绑定。

在第一个例子中,一个是修改一个对象的属性,该对象存储在sys.modules导入它的所有模块中,并且对所有模块都是通用的。在第二个示例中,一个是修改导入模块的全局范围。

如果要按照以下方式做某事

 from foo import fobaz
 fobaz.foobar = 7

然后该更改传播到其他导入模块,因为一个不会覆盖全局引用而是跟随它来修改它指向的对象的属性。所以本质上,只要不覆盖全局绑定,您就应该能够修改可变对象。

我认为像这样的东西是你能够干净利落地在 python 中获得真正全局的最接近的东西。作为一种语言,它非常重视命名空间。

于 2010-12-14T07:11:49.603 回答
4

考虑到全局变量通常被认为是一件坏事,我怀疑“真正的全局”变量将是一件非常糟糕的事情。

获得类似行为的另一种方法是在单例对象中使用类范围属性,然后将其导入。然后更清楚您从哪里获取“全局”变量。

于 2010-12-14T06:18:01.530 回答