例如,我有一个
class BaseHandler(object):
def prepare(self):
self.prepped = 1
我不希望每个人都是BaseHandler的子类,也想要实现准备必须记住调用
super(SubBaseHandler, self).prepare()
有没有办法确保运行超类方法,即使子类也实现了prepare?
答案 0 :(得分:14)
我使用元类解决了这个问题。
使用元类允许BaseHandler
的实现者确保所有子类都将调用超类prepare()
而不调整任何现有代码。
元类在两个类上查找prepare
的实现,然后用调用superclass.prepare
后跟subclass.prepare
的子类覆盖子类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
答案 1 :(得分:4)
告诉开发人员定义prepare_hook
而不是prepare
,但是
告诉用户致电prepare
:
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
这就是它的目的。
答案 2 :(得分:3)
接受你必须告诉人们继承你的类,以便在覆盖它时调用基本方法。其他每一个解决方案都要求你解释它们做其他事情,或者涉及一些可能被规避的非pythonic黑客攻击。
Python的对象继承模型被设计为开放的,任何尝试以另一种方式尝试都会使问题过于复杂,而这个问题实际上并不存在。告诉每个人使用你的东西要么遵循你的“规则”,要么程序会搞砸。
答案 3 :(得分:2)
一个没有太大魔力的明确解决方案是维护一个准备回调列表:
class BaseHandler(object):
def __init__(self):
self.prepare_callbacks = []
def register_prepare_callback(self, callback):
self.prepare_callbacks.append(callback)
def prepare(self):
# Do BaseHandler preparation
for callback in self.prepare_callbacks:
callback()
class MyHandler(BaseHandler):
def __init__(self):
BaseHandler.__init__(self)
self.register_prepare_callback(self._prepare)
def _prepare(self):
# whatever
答案 4 :(得分:0)
一般情况下,您可以尝试使用__getattribute__
来实现这样的事情(直到有人覆盖此方法的那一刻),但它违背了Python的想法。有理由能够在Python中访问私有对象成员。原因在import this