python - 注册所有子类

时间:2018-01-11 09:51:40

标签: python

我有一个class Step,我想通过许多子类派生。我希望每个来自Step的课程都是"注册"通过我选择的名称(不是班级名称),我可以稍后拨打Step.getStepTypeByName()

像这样,只有工作:):

class Step(object):
    _STEPS_BY_NAME = {}

    @staticmethod
    def REGISTER(cls, name):
        _STEPS_BY_NAME[name] = cls

class Derive1(Step):
    REGISTER(Derive1, "CustomDerive1Name")
    ...

class Derive2(Step):
    REGISTER(Derive2, "CustomDerive2Name")
    ...

2 个答案:

答案 0 :(得分:1)

您的解决方案有三个原因无效。

第一个问题是_STEPS_BY_NAME仅作为Step类的属性存在,因此Step.REGISTER无法在不引用_STEPS_BY_NAME的情况下访问Step类。如果你必须使它成为classmethod(参见下文)

第二个是您需要明确使用Step.REGISTER(cls) - REGISTER类之外不存在名称Step

第三个原因是在class语句的主体内,尚未创建类对象而不绑定它的名称,所以此时你不能引用类本身。

我,你想要这个:

class Step(object):
    _STEPS_BY_NAME = {}

    # NB : by convention, "ALL_UPPER" names denote pseudo-constants
    @classmethod
    def register(cls, name):
        # here `cls` is the current class 
        cls._STEPS_BY_NAME[name] = stepclass

class Derive1(Step):
    ...

Step.register(Derive1, "CustomDerive1Name")


class Derive2(Step):
    ...

Step.register(Derive2, "CustomDerive2Name")

现在对Step.register做一个小修改,你可以将它用作类装饰器,使事情更加清晰:

class Step(object):
    _STEPS_BY_NAME = {}

    @classmethod
    def register(cls, name):
        def _register(stepclass):
            cls._STEPS_BY_NAME[name] = stepclass
            return stepclass 
        return _register 


@Step.register("CustomDerive1Name")
class Derive1(Step):
    ...



@Step.register("CustomDerive2Name")
class Derive2(Step):
    ...

作为最后一点:除非你有一个令人信服的理由在基类本身注册你的子类,否则最好使用模块级变量和函数(Python模块实际上是一个一种单身人士):

# steps.py

class Step(object):
    #....

_STEPS_BY_NAME = {}

def register(name):
   def _register(cls):
       _STEPS_BY_NAME[name] = cls
       return cls
   return _register

def get_step_class(name):
    return _STEPS_BY_NAME[name]

在你的其他模块中

import steps

@steps.register("CustomDerive1Name")
class Derive1(steps.Step):
    # ...

这里的要点是避免对你的Step课程给予太多的责任。我不知道你的具体使用案例,所以我不知道哪种设计最适合你的需要,但我在很多项目中都使用了最后一种,到目前为止一直都很好。

答案 1 :(得分:0)

你很亲密。使用此

java.lang.SecurityException: Injecting to another application 
           requires **INJECT_EVENTS** permission

警告:根据您要实现的目标,可能有更好的方法。从字符串到方法的这种映射是维护的噩梦。如果要更改方法的名称,则必须记住在多个位置更改它。您也无法从IDE获得任何自动完成帮助。