我很惊讶地发现了
import foo
和
from foo import *
对全球会员有不同的影响。我想确认我的实验是正确的行为。
在第一个示例中,更改模块foo中的成员将反映在导入foo的所有代码中。但是,在后一种情况下更改该成员似乎只会影响导入它的文件。换句话说,使用后面的方法将为每个导入文件提供foo中自己的成员副本。
我想要的行为是从所有文件中访问foo.x,能够从所有文件中更改它,并将更改反映在所有文件中(如果愿意,可以使用真正的全局文件)。
答案 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)
考虑到全局变量通常被认为是一件坏事,我怀疑“真正的全局”变量将是一件非常糟糕的事情。
获得类似行为的另一种方法是在单例对象中使用类范围属性,然后只导入它。然后更清楚地从哪里获得“全局”变量。