Python:如何在创建时使用父类注册所有子类

Yon*_*tan 4 python inheritance class registration

我有python类树,每个树都由一个抽象基类和许多派生的具体类组成.我希望通过基类方法可以访问所有具体类,并且我不想在子类创建期间指定任何内容.

这就是我想象的解决方案:

class BaseClassA(object):
    # <some magic code around here>
    @classmethod
    def getConcreteClasses(cls):
        # <some magic related code here>

class ConcreteClassA1(BaseClassA):
    # no magic-related code here

class ConcreteClassA2(BaseClassA):
    # no magic-related code here
Run Code Online (Sandbox Code Playgroud)

尽可能地,我更喜欢将"魔术"写成一种设计模式.我希望能够将它应用于不同场景中的不同类树(即添加一个与"BaseClassB"及其具体类相似的树).

谢谢上网!

der*_*ers 9

这是一个使用PEP 487__init__subclass__中定义的现代 python (3.6+) 的简单解决方案。它允许您避免使用元类。

class BaseClassA(object):
    _subclasses = [] 

    @classmethod
    def get_concrete_classes(cls):
        return list(cls._subclasses)

    def __init_subclass__(cls):
        BaseClassA._subclasses.append(cls)


class ConcreteClassA1(BaseClassA):
    pass  # no magic-related code here


class ConcreteClassA2(BaseClassA):
    pass  # no magic-related code here


print(BaseClassA.get_concrete_classes())
Run Code Online (Sandbox Code Playgroud)


gur*_*lex 6

您可以使用元类:

class AutoRegister(type):
    def __new__(mcs, name, bases, classdict):
        new_cls = type.__new__(mcs, name, bases, classdict)
        #print mcs, name, bases, classdict
        for b in bases:
            if hasattr(b, 'register_subclass'):
                b.register_subclass(new_cls)
        return new_cls


class AbstractClassA(object):
    __metaclass__ = AutoRegister
    _subclasses = []

    @classmethod
    def register_subclass(klass, cls):
        klass._subclasses.append(cls)

    @classmethod
    def get_concrete_classes(klass):
        return klass._subclasses


class ConcreteClassA1(AbstractClassA):
    pass

class ConcreteClassA2(AbstractClassA):
    pass

class ConcreteClassA3(ConcreteClassA2):
    pass


print AbstractClassA.get_concrete_classes()
Run Code Online (Sandbox Code Playgroud)

我个人非常警惕这种魔法.不要在代码中加入太多内容.