class方法中的access(只读)全局变量

时间:2014-11-19 13:39:07

标签: class python-3.x methods import global

我有类Config()加载配置选项。我创建了一个名为cfg的类的实例 然后我有很多A,B,C类,必须只读成员来自cfg。

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。

有什么更好/更清洁/更简单吗?

1 个答案:

答案 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 *。)