我正在尝试构建一个包含Service
个实例的Registry
类。 Registry
和Service
类如下;
class Registry:
def __init__(self, registrar):
self.registrar = registrar
def get(self, key):
layers = key.split('.')
value = self.registrar
for item in layers:
value = value[item]
return value
class Service:
instance = None
@classmethod
def boot(cls, object, configuration = {}):
if cls.instance is None:
cls.instance = object(configuration)
我目前想要的是在调用boot
函数之后,注册表函数应该可以从Service
类静态访问,而无需在Service
类中定义函数。因此,在使用以下代码启动后,我想使用get
函数。
Service.boot(Config, {'a' : 'b'});
Service.get('a');
注意:Config对象是Registry
的扩展我尝试了__getattr__
魔术方法,但它并不适用于静态方法。
我已尝试__call__
但之后我需要拨打Service().get()
这不是我想要的。
那么,有可能在python中实现这一点吗?我不想在Service
图层中重新定义类方法。
注意:在PHP中,存在__callStatic()
函数,它完全符合我的要求。但是,我无法在python上找到实现。
答案 0 :(得分:2)
如果您可以略微修改您的通话模式,我可以想象它是可行的:
cfg = Service.boot(Config, {'a' : 'b'})
cfg.get('a')
通过这种方式,如果让__getattr__
返回提供这些方法的对象,则可以完美地使其与boot()
一起使用。
如果没有,您可以尝试以下方法之一:
cfg.instance.get('a')
给Service
一个元类:
class Registry:
def __init__(self, registrar):
self.registrar = registrar
def get(self, key):
layers = key.split('.')
value = self.registrar
for item in layers:
value = value[item]
return value
class DeflectToInstance(type):
def __getattr__(selfcls, a): # selfcls in order to make clear it is a class object (as we are a metaclass)
try:
# first, inquiry the class itself
return super(Meta, selfcls).__getattr__(a)
except AttributeError:
# Not found, so try to inquiry the instance attribute:
return getattr(selfcls.instance, a)
class Service:
__metaclass__ = DeflectToInstance
instance = None
@classmethod
def boot(cls, NewCls, configuration={}):
if cls.instance is None:
cls.instance = NewCls(configuration)
Service.boot(Registry, {'a': 'b'})
print Service.get('a')
这里的元类提供了一种适当的方法来将类的属性访问转移到其属性之一。
请注意,在Py3下,语法略有不同。 IIRC,它是
class Service(metaclass=DeflectToInstance):
(但是,对于我来说,使用Service
类来进行这种封装似乎有点不对。
您可以在一个地方从我的第一个想法开始cfg = boot(...)
,然后使用cfg
进行每次访问。您甚至(误导性地)将其命名为Config
:
class Registry:
def __init__(self, registrar):
self.registrar = registrar
def get(self, key):
layers = key.split('.')
value = self.registrar
for item in layers:
value = value[item]
return value
cfg = Registry(...)
或
Config = Registry(...)
然后随时随地使用cfg
(或Config
)。)