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

D.C*_*.C. 12 python python-import

我很惊讶地发现了这一点

import foo
Run Code Online (Sandbox Code Playgroud)

from foo import *
Run Code Online (Sandbox Code Playgroud)

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

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

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

aar*_*ing 15

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

当一个人这样做

import foo
Run Code Online (Sandbox Code Playgroud)

然后foo成为引用该模块的全局名称foo.当一个人这样做

foo.bar = 7
Run Code Online (Sandbox Code Playgroud)

然后遵循引用并foo加载对象.然后7存储在bar属性中.

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

当一个人这样做

from foo import bar
Run Code Online (Sandbox Code Playgroud)

globals()['bar']设置为参考foo.bar.什么后来呢

 bar = 7
Run Code Online (Sandbox Code Playgroud)

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

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

如果一个人要做的事情

 from foo import fobaz
 fobaz.foobar = 7
Run Code Online (Sandbox Code Playgroud)

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

我认为像这样的东西是最接近你能够干净利落地进入python中的真正全局的东西.作为一种语言,它极大地重视名称空间.