全局变量和模块导入

时间:2019-07-15 06:00:17

标签: python module global-variables

我已经使用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模块导入如此挑剔?

2 个答案:

答案 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