确认导入*和xxx导入*之间的区别
我很惊讶地发现
import foo
和
from foo import *
对全球成员产生了不同的影响。我想确认我的实验是正确的行为。
在第一个示例中,更改foo模块中的成员将反映在所有导入foo的代码中。但是,在以后的情况下更改该成员似乎仅影响导入该成员的文件。换句话说,使用后一种方法将为每个导入文件提供其自己的foo成员副本。
我想要的行为是可以从所有文件访问foo.x,可以从所有文件更改它,并在所有文件中反映该更改(如果愿意,则为真正的全局)。
-
是的,您的观察是正确的。这是绑定在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达到真正全局性的最接近的东西。作为一种语言,它极大地重视名称空间。