Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带有_init_子类和子类注册表的注册表模式_Python_Class_Oop_Metaclass_Registry Pattern - Fatal编程技术网

Python 带有_init_子类和子类注册表的注册表模式

Python 带有_init_子类和子类注册表的注册表模式,python,class,oop,metaclass,registry-pattern,Python,Class,Oop,Metaclass,Registry Pattern,我想创建一个设置注册表。我还希望能够在宏类别中分组设置 以下简化示例适用于单个注册表: class RegistryHolder: registry = {} def __init_subclass__(cls, setting_name=None, **kwargs): super().__init_subclass__(**kwargs) cls.registry[setting_name] = cls class SettingOne(R

我想创建一个设置注册表。我还希望能够在宏类别中分组设置

以下简化示例适用于单个注册表:

class RegistryHolder:
    registry = {}

    def __init_subclass__(cls, setting_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.registry[setting_name] = cls

class SettingOne(RegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(RegistryHolder, setting_name='SettingTwo'):
    pass
结果是:

print(RegistryHolder.registry)

{'SettingOne': <class '__main__.SettingOne'>,
 'SettingTwo': <class '__main__.SettingTwo'>}
这显然不起作用,因为当我将
RegistryHolder
子类化时,我正在将
User/System
类作为注册表的一部分进行“注册”,例如,对于
UserRegistryHolder.registry
我得到:

{'SettingOne': <class '__main__.SettingTwo'>, 
 'SettingTwo': <class '__main__.SettingTwo'>, 
 None: <class '__main__.UserRegistryHolder'>}
{'SettingOne':,
“设置二”:,
无:}
所以有几个问题:

  • 我问错问题了吗
  • 我是不是想得太多了
  • 您将如何干净地创建这样一个接口(欢迎使用替代方案)

假设
RegistryHolder
只是一个基类(模板),不应累加所有设置,而其子持有人
UserRegistryHolder/SystemRegistryHolder
应保留“各自的”设置:

class RegistryHolder:
    registry = {}

    def __init_subclass__(cls, setting_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        parent = cls.__bases__[0]
        if setting_name:
            parent.registry[setting_name] = cls  # add setting to parent sub-holder
        else:
            cls.registry = {}   # init registry for sub-holder


class UserRegistryHolder(RegistryHolder):
    pass

class SettingOne(UserRegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(UserRegistryHolder, setting_name='SettingTwo'):
    pass

class SystemRegistryHolder(RegistryHolder):
    pass

class SettingA(SystemRegistryHolder, setting_name='SettingA'):
    pass

class SettingB(SystemRegistryHolder, setting_name='SettingB'):
    pass


print(RegistryHolder.registry)
print(UserRegistryHolder.registry)
print(SystemRegistryHolder.registry)
输出(连续):

{}
{'SettingOne':,'SettingTwo':}
{'SettingA':,'SettingB':}

让我们详细说明一下:
RegistryHolder
只是一个基类,不应该累加所有设置,而它的子持有者
User/System
应该这样做,对吧?看起来你没有区分注册表和注册表持有者<代码>设置a是注册表,而不是注册表持有者。(或者,您可能希望区分注册表持有者和注册表持有者。)您希望宏类别中具有分组设置的此设置注册表看起来像什么?
{'SettingOne': <class '__main__.SettingTwo'>, 
 'SettingTwo': <class '__main__.SettingTwo'>, 
 None: <class '__main__.UserRegistryHolder'>}
class RegistryHolder:
    registry = {}

    def __init_subclass__(cls, setting_name=None, **kwargs):
        super().__init_subclass__(**kwargs)
        parent = cls.__bases__[0]
        if setting_name:
            parent.registry[setting_name] = cls  # add setting to parent sub-holder
        else:
            cls.registry = {}   # init registry for sub-holder


class UserRegistryHolder(RegistryHolder):
    pass

class SettingOne(UserRegistryHolder, setting_name='SettingOne'):
    pass

class SettingTwo(UserRegistryHolder, setting_name='SettingTwo'):
    pass

class SystemRegistryHolder(RegistryHolder):
    pass

class SettingA(SystemRegistryHolder, setting_name='SettingA'):
    pass

class SettingB(SystemRegistryHolder, setting_name='SettingB'):
    pass


print(RegistryHolder.registry)
print(UserRegistryHolder.registry)
print(SystemRegistryHolder.registry)
{}
{'SettingOne': <class '__main__.SettingOne'>, 'SettingTwo': <class '__main__.SettingTwo'>}
{'SettingA': <class '__main__.SettingA'>, 'SettingB': <class '__main__.SettingB'>}