确认import *和xxx import之间的区别*

时间:2010-12-14 06:10:39

标签: python python-import

我很惊讶地发现了

import foo

from foo import *

对全球会员有不同的影响。我想确认我的实验是正确的行为。

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

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

2 个答案:

答案 0 :(得分:14)

是的,您的观察是正确的。这是绑定在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中干净利落地获得真正全局的最接近的东西。作为一种语言,它极大地重视名称空间。

答案 1 :(得分:4)

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

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