2024-09-30 18:22:28 发布
网友
例如,我有一个
class BaseHandler(object): def prepare(self): self.prepped = 1
我不希望每个子类BaseHandler并希望实现prepare的人都必须记住调用
super(SubBaseHandler, self).prepare()
即使子类也实现了prepare,是否有办法确保超类方法运行
只需接受这样一个事实,即在重写基类时,您必须告诉类的子类化人员调用基类方法。其他任何解决方案要么需要你解释他们做其他事情,要么涉及一些非pythonic的黑客,这些黑客也可以规避
Python的对象继承模型被设计为开放的,任何尝试另一种方式都只会使问题过于复杂,而这个问题实际上并不存在。只要告诉所有使用你的东西的人要么遵守你的“规则”,否则程序就会一团糟
我已经用元类解决了这个问题
使用元类允许BaseHandler的实现者确保所有子类都将调用超类prepare(),而不需要调整任何现有代码
BaseHandler
prepare()
元类在两个类上查找prepare的实现,然后用调用superclass.prepare的子类prepare覆盖子类prepare,该子类后跟subclass.prepare
prepare
superclass.prepare
subclass.prepare
class MetaHandler(type): def __new__(cls, name, bases, attrs): instance = type.__new__(cls, name, bases, attrs) super_instance = super(instance, instance) if hasattr(super_instance, 'prepare') and hasattr(instance, 'prepare'): super_prepare = getattr(super_instance, 'prepare') sub_prepare = getattr(instance, 'prepare') def new_prepare(self): super_prepare(self) sub_prepare(self) setattr(instance, 'prepare', new_prepare) return instance class BaseHandler(object): __metaclass__ = MetaHandler def prepare(self): print 'BaseHandler.prepare' class SubHandler(BaseHandler): def prepare(self): print 'SubHandler.prepare'
使用它看起来像这样:
>>> sh = SubHandler() >>> sh.prepare() BaseHandler.prepare SubHandler.prepare
告诉开发人员定义prepare_hook而不是prepare,但是 告诉用户调用prepare:
prepare_hook
class BaseHandler(object): def prepare(self): self.prepped = 1 self.prepare_hook() def prepare_hook(self): pass class SubBaseHandler(BaseHandler): def prepare_hook(self): pass foo = SubBaseHandler() foo.prepare()
如果您想要更复杂的多个子类prepare调用链接,那么您的开发人员应该真正使用super,因为这正是它的目的
super
只需接受这样一个事实,即在重写基类时,您必须告诉类的子类化人员调用基类方法。其他任何解决方案要么需要你解释他们做其他事情,要么涉及一些非pythonic的黑客,这些黑客也可以规避
Python的对象继承模型被设计为开放的,任何尝试另一种方式都只会使问题过于复杂,而这个问题实际上并不存在。只要告诉所有使用你的东西的人要么遵守你的“规则”,否则程序就会一团糟
我已经用元类解决了这个问题
使用元类允许
BaseHandler
的实现者确保所有子类都将调用超类prepare()
,而不需要调整任何现有代码元类在两个类上查找
prepare
的实现,然后用调用superclass.prepare
的子类prepare覆盖子类prepare,该子类后跟subclass.prepare
使用它看起来像这样:
告诉开发人员定义
prepare_hook
而不是prepare
,但是 告诉用户调用prepare
:如果您想要更复杂的多个子类
prepare
调用链接,那么您的开发人员应该真正使用super
,因为这正是它的目的相关问题 更多 >
编程相关推荐