确认导入*和来自xxx导入*之间的差异

2022-03-31 00:00:00 python python-import

问题描述

我惊讶地发现

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
然后,更改将传播到其他导入模块,因为您不会覆盖全局引用,而是跟随全局引用来修改它所指向对象的属性。因此,从本质上讲,只要不覆盖全局绑定,您就应该能够修改可变对象。

我认为像这样的东西是您将能够干净利落地实现真正的全局化的最接近的东西。作为一种语言,它非常重视命名空间。

相关文章