我有类Config()加载配置选项。我创建了一个名为cfg的类的实例
然后我有很多A,B,C类,必须
from mylib.config import *
from mylib.A import *
from mylib.B import *
from mylib.C import *
cfg = Config(filename)
a = A()
a.do_things()
例如在A构造函数中我有:
def __init__(self):
self.name = cfg.name
问题是我在运行时“NameError:name'cfg'未定义”在线自我.name = cfg.name
我首先想到的是我在声明cfg之前导入mylib.A,mylib.B和mylib.C的东西 所以我搬了
cfg = Config(filename)
导入mylib.A ... B ... C之前。但仍然是同样的错误。
可能的解决方案:
1.将对象'cfg'作为参数传递,但我必须更改所有A,B,C类中所有方法的签名,并且我觉得它不干净,因为它会在所有方法中相乘相同的参数。
2.为类A,B,C创建私有成员_cfg。更好但又不是很好,数据乘以
3.将类定义+实例声明放在一个文件中,并将其导入mylib.A,mylib.B和mylib.C:AFAISI这是最好的解决方案,但仍然不是我的口味,因为我混合了类定义和实例声明,我喜欢在类文件中只有类定义
4.为避免同一文件中的类定义和实例化,我可以创建一个'init.py'
from mylib.config import *
cfg = Config(filename)
然后在mylib.A,mylib.B和mylib.C中导入init ...但是我已经有一个带有日志函数的init文件,并且由于Config构造函数使用这些函数,它会创建循环导入问题(init.py在mylib.config.py类声明文件中导入,并在init.py中导入mylib.config,以避免它我应该有init.py和init_config.py。
有什么更好/更清洁/更简单吗?
答案 0 :(得分:0)
如何在mylib.config
内创建一个initialize
函数,该函数会创建一个全局配置对象。
config_obj = None
#todo: pick a better name for this
class Config:
def __init__(self, filename):
pass
#todo: definition goes here.
def initialize(filename):
global config_obj
config_obj= Config(filename)
然后,在主文件中,在对模块A B或C执行任何操作之前调用该函数。
from mylib.config import *
from mylib.A import *
from mylib.B import *
from mylib.C import *
initialize(filename)
a = A()
a.do_things()
不要忘记import config
需要引用config_obj
的任何模块。
#mylib.a
import config
class Whatever:
def __init__(self):
self.name = config.cfg_obj.name
请注意,您不应将import config
替换为from config import *
,因为当主文件调用cfg_obj
时,A initialize
的副本将无法正确更新。< / p>
如果你不喜欢你的类模块有函数或全局变量,你可以使initialize
成为Config类的静态方法,它返回Config的单例实例。
#singleton Config class. Only one instance of it should ever exist.
#Users, please don't call Config(filename). use get_instance() instead.
class Config:
instance = None
def __init__(self, filename):
pass
#definition goes here...
@staticmethod
def initialize(filename):
if Config.instance is not None:
msg = "singleton Config has already been initialized"
raise Exception(msg)
#this is the only place Config(filename) should ever be called.
Config.instance = Config(filename)
return Config.instance
@staticmethod
def get_instance():
if Config.instance is None:
msg = "can't get instance because it hasn't been initialized yet"
raise Exception(msg)
return Config.instance
(可能有更好的方法来制作singleton in Python。我只是采用一种简单的方法来说明目的。)
然后在主文件中初始化:
from mylib.config import *
from mylib.A import *
from mylib.B import *
from mylib.C import *
Config.initialize(filename)
a = A()
a.do_things()
获取模块中的实例:
#mylib.a
import config
class Whatever:
def __init__(self):
self.name = config.Config.get_instance().name
(根据这种方法,如果您愿意,我认为您可以在模块中from config import *
。)