具有__init_subclass__和可子分类的注册表的注册表模式 [英] Registry pattern with __init_subclass__ and sub-classable registry

查看:79
本文介绍了具有__init_subclass__和可子分类的注册表的注册表模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个设置注册表.我还希望能够对宏类别中的设置进行分组.

I want to create a settings registry. I also want to be able to group settings in macro-categories.

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

The following simplified example works with a single registry:

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'>}

我想按宏类别对设置进行分组,而不必每次都重写__init_subclass__().像这样:

I would like to group the settings by macro categories without rewriting the __init_subclass__() each time. Something like:

class UserRegistryHolder(RegistryHolder):
    pass

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

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

class SystemRegistryHolder(RegistryHolder):
    pass

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

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

这显然是行不通的,因为当我将RegistryHolder子类化时,我正在将User/System类作为注册表的一部分``注册'',例如对于UserRegistryHolder.registry,我得到了:

This obviously does not work because when I subclass the RegistryHolder, I am 'registering' the User/System classes as part of the registry, e.g. for UserRegistryHolder.registry I get:

{'SettingOne': <class '__main__.SettingTwo'>, 
 'SettingTwo': <class '__main__.SettingTwo'>, 
 None: <class '__main__.UserRegistryHolder'>}

那么几个问题:

  • 我问错了一个问题吗?
  • 我是否想得太多?
  • 您将如何干净地创建这样的界面(欢迎使用替代方法)?

推荐答案

假定RegistryHolder只是基类(模板),并且不应累积所有设置,而希望其子持有人UserRegistryHolder/SystemRegistryHolder确实保留了相应"设置:

Assuming that RegistryHolder is only a base class (template) and should not accumulate all settings, while its sub-holders UserRegistryHolder/SystemRegistryHolder are expected do keep the "respective" settings:

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'>}

这篇关于具有__init_subclass__和可子分类的注册表的注册表模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆