我有一些类变量应该在创建任何类实例之前定义。它没有默认值,只有使用该类的人才能启动它。
我做了以下事情:
class Foo:
_inited = False # flag to show if Foo.static_init was called
_FILE_PATH = None # this var should be inited before class using
@classmethod
def static_init(cls, file_path):
cls._inited = True
cls._FILE_PATH = file_path
def __init__(self):
if not Foo._inited:
raise Exception('Foo.static_init should be called first.')
看起来很难看,有什么方法可以更好地进行静态初始化?
答案 0 :(得分:0)
您似乎拥有的类型Foo
取决于值file_path
。但是,我不完全确定这是否是你想要的,因为你可能有XY problem。
可以使用这样的定义来实现:
def make_Foo(file_path):
class Foo:
_FILE_PATH = file_path
def __init__(self):
pass
return Foo
在此表单中,如果不提供Foo
参数,则用户无法获取类型file_path
。要使用这样的类,我会这样做:
Foo = make_Foo("/var/tmp")
my_foo = Foo()
这样做的另一个好处是,用户可以通过提供Foo
的不同值来获取file_path
类型的多个实例:
Foo2 = make_Foo("/var/log")
Foo3 = make_Foo("/home")
如果您想在项目中的任何地方使用{em>实例化版本的Foo
,那么您只需在某个共享模块中添加Foo = make_Foo(...)
。
答案 1 :(得分:0)
我决定采用原创方式,但可以重复使用解决方案。此类装饰器可用于强制cls.static_init()
调用。
def static_init(cls_to_decorate):
class Wrapper(cls_to_decorate):
_static_init_called = False
def __new__(cls, *args, **kwargs):
if not Wrapper._static_init_called:
raise Exception('{}.static_init() should be called.'.format(cls_to_decorate.__name__))
return super().__new__(cls, *args, **kwargs)
@classmethod
def static_init(cls, *args, **kwargs):
Wrapper._static_init_called = True
return super().static_init(*args, **kwargs)
return Wrapper
用法:
@static_init
class Foo:
_PARAM = None
def test(self):
print(Foo._PARAM)
f = Foo() #Exception: Foo.static_init() should be called.
@static_init
class Foo:
_PARAM = None
@classmethod
def static_init(cls, param):
cls._PARAM = param
def test(self):
print(Foo._PARAM)
Foo.static_init('param')
f = Foo()
f.test() # param