我已经使用Python多年了,创建用于分发的新模块仍然令人困惑,难以置信。真是令人沮丧。我需要一个专家来解释。
我最近发现,根据在__init__.py
文件中导入模块的方式,在子模块中设置全局变量的行为会有所不同。
我有这样的设置:
prime.py
import sub
sub.somevar = False
sub.show()
sub.py
somevar = True
def show():
global somevar
print("somevar is {}".format(somevar))
此代码产生预期的输出:
somevar is False.
当main.py和sub.py位于同一目录中时。当我使用setuptools将sub
做成一个单独的可安装模块时,它将停止工作。
我的sub
可安装模块目录结构如下:
# ls
setup.py sub README.md
# ls sub
__init__.py sub.py
__init__.py
包含以下文本:
from .sub import *
对于安装和分发适用于Python2和Python3的模块,此设置似乎非常有用。
问题在于,当我使用prime.py
导入全局变量设置时,该全局变量设置已损坏;从somevar
设置prime.py
的任何尝试都不会按预期改变sub.py
函数的变量。我得到了输出:
somevar is True
这到底是怎么回事?为什么python模块导入如此挑剔?
答案 0 :(得分:1)
它与您的项目结构无关,而仅与导入方式有关。
我认为这很容易理解。由于在使用somevar
时隐含from x import *
的情况下from x import somevar
是一种值类型,因此您会在当前名称空间中获得somevar
的副本。
由于它只是一个副本,因此更改它不会更改子模块中的somevar
。
但是如果somevar
是一个列表,例如:
# In sub.py
somevar = [True]
您通过
对其进行了更改# In prime.py
somevar[0] = False
然后它将起作用。
答案 1 :(得分:0)
要快速修复,您可以简单地使用“ setter”“ getter”行为:
prime.py
import sub
sub.set_somevar(False)
myFalseVar = sub.get_somevar()
sub.py
somevar = True
def get_somevar():
global somevar
return somevar
def set_somevar(var):
global somevar
somevar = var