我无法理解为什么在使用import
时从另一个模块导入全局变量能按预期进行,但是在使用from x import *
时,全局变量似乎不会在其自己的模块中更新< / p>
假设我有2个文件, 一个.py:
def change(value):
global x
x = value
x = "start"
和two.py:
from one import *
print x
change("updated")
print x
我希望:
start
updated
但是我得到...
start
start
如果我正常导入模块,它将按预期工作
import one
print one.x
one.change("updated")
print one.x
结果...
start
updated
鉴于我无法更改ony.py对全局变量的使用(不是我的错),并且two.py旨在作为one.py的包装器*,我真的很想避免使用为了实现一个顽固的变量,在整个two.py中使用了one.
命名空间。
如果不可能,那么对新手进行的移植可能会帮助我避免再次陷入这种困境。我知道one.x正在更新,但是two.x不遵守更新,但是我不知道为什么。
答案 0 :(得分:1)
您可以将软件包视为命令。包中的每个函数和变量都作为该字典中的键列出,您可以使用globals()
查看该字典。
从另一个包中导入对象时,会将对象的引用复制到您自己的包中,其名称为(通常是相同的,如果您import <var> as <name>
则不同)。
通过在另一个包中设置值,您可以用一个新值覆盖该包中的键,但是您的引用将指向旧的键。
我们可以使用dict作为类比来演示该过程:
# Our 'packages'
one = {'x': 'start'}
two = {}
# Equivalent of our import
two['x'] = one['x']
# Variable updated in `one'
one['x'] = 'updated'
# ... and accessed in `two`
print(two['x']) # Still 'start'
我们不希望仅仅因为我们重写了two
中的值而更新one
字典。
只要不通过覆盖变量破坏指针,就可以修改对象。例如,如果x
是字典,则可以在字典内部更改一个值,而这两个变量仍将指向同一对象。
或者,您可以像这样将变量附加到函数:
def change(value):
change.x = value
这通过确保我们对同一对象进行突变来完成相同的工作。
一个更好的答案可能是将两个物品包装在一起,如果它们需要一起旅行:
class Changer:
x = 'start'
@classmethod
def change(cls, value):
cls.x = value
但是,此时,我们可以将值直接修改为属性:
Changer.x = 'updated'
这可能是最简单的。
答案 1 :(得分:0)
这可能是您在two.py中可以做的最好的事情:
import one
from one import x
def change(value):
one.change(value)
global x
from one import x