许多人说,here和here提供的方法解决了他们的变量共享问题,但是它们都不适合我的用例,因为所有配置必须 >像下面这样编写。
# config.py
class Config(object):
var = None
我的项目的结构看起来像
├── config.py
├── main.py
├── subfolder
| ├── change_config.py
在此项目中,main.py
将调用change_config.py
,并且它们都可以访问config.py
中定义的变量。重要的是,change_config.py
将修改仅在运行时知道其值的变量(又名var
)。
但是尚不清楚我应该如何在Config()
和opt
之间共享实例化的main.py
(又名change_config.py
)。我尝试跟随但没有运气。问题是
Config()
中实例化了另一个change_config.py
,则main.py
中的另一个实例将被清除。opt
中的名字change_config.py
不会被解析# main.py
import config
from subfolder import change_config
opt = config.Config()
print(opt.var)
change_config.change_config()
print(opt.var)
# change_config.py
import config
def change_config():
opt.var = 10
如果我运行main.py
,那么我将拥有
NameError: name 'opt' is not defined
,因为opt
从未在change_config.py
中声明,所以可以预期。
如果我将change_config.py
更改为
# change_config.py
import config
opt = config.Config()
def change_config():
opt.var = 10
我在其中声明了另一个opt
。没有错误,但返回了
None
None
这也是可以预期的,因为opt
中声明的main.py
被change_config.py
中的那个擦除了。但是预期的输出应该是
None
10
所以问题是如何与opt
共享main.py
中的change_config.py
答案 0 :(得分:0)
让我们先来看一下Config.var
和Config().var
之间在python方面的区别。像Python中的其他所有内容一样,类是一个对象。类具有名称空间,因此Config.var
是该名称空间中的变量。
实例化Config
时,用opt = Config()
说,opt现在是一个对象,也带有名称空间。首先,当您请求值opt.var
时,由于继承的工作原理,它返回Config.var
:如果对象没有属性,则在类中查找,然后在父类中查找等等。但是,当您分配opt.var = 10
时,您是在分配到实例的名称空间中。现在,当您请求opt.var
的值时,它不再查看Config.var
,因为opt
具有自己的var
属性。
现在请记住,opt
中的main
和opt
中的change_config
是完全不同的实例,除了它们共享同一类外,它们不会互相影响。因此,当您设置change_config.opt.var = 10
时,请求main.opt.var
仍会返回None
,因为实际的属性main.opt.var
本身并不存在:它是从类中返回Config.var
命名空间。
因此,现在您可以使用几个选项。
第一个方法是完全不用实例化任何东西。您可以保留您的类变量config.Config.var
,然后在类名称空间中进行更新。代码如下:
main.py
from config import Config
from subfolder.change_config import change_config
print(Config.var)
change_config()
print(Config.var)
config.py
class Config:
var = None
子文件夹/change_config.py
from config import Config
def change_config():
Config.var = 10
除了将导入更改为相对导入并从object
中删除显式继承之外,您的代码仅被修改为使用Config
作为命名空间,而没有实例化它。
第二种方法是实例化Config
,但是将引用放置在需要该引用的每个人都可以访问的地方。在这一点上,config.py
实际上应该维护共享引用,因为那是存储实际配置的内容。我还建议完全删除类变量Config.var
,以避免确切地引起您现在的困惑:
main.py
from config import opt
from subfolder.change_config import change_config
print(opt.var)
change_config()
print(opt.var)
config.py
class Config:
def __init__(self):
self.var = None
opt = Config()
子文件夹/change_config.py
from config import opt
def change_config():
opt.var = 10
您可以通过在Config
的末尾添加del Config
来使您的配置成为config.py
实例的更深层次。这将使创建另一个相互冲突的类的实例变得更加困难,因为它将无法通过模块轻松获得。此时,对Config
的唯一引用将是通过opt
的继承层次结构。
答案 1 :(得分:-1)
您可以按如下所示更改应用程序,这将对您有所帮助
在config.py
x = 0
在change_config.py
import config
def change_config():
config.x = 10 #change the global config variable
和main.py
import config
from subfolder import change_config
print(config.x)
change_config.change_config()
print(config.x)
运行main.py
0
10
编辑
使用 singleton 类
在config.py
class Config(object):
var = None
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Config, cls).__new__(cls)
return cls.instance
在main.py
from config import Config
from subfolder import change_config
opt = Config()
print('memory address :%s'%id(opt))
print(opt.var)
change_config.change_config()
print(opt.var)
在change_config.py
from config import Config
opt = Config()
print('memory address :%s'%id(opt))
def change_config():
opt.var = 10
您将得到如下输出
memory address :140185708587536
memory address :140185708587536
None
10