是的,你的观察是正确的。这是绑定在 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 中获得真正全局的最接近的东西。作为一种语言,它非常重视命名空间。