我有一个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")
...
答案 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获得任何自动完成帮助。