我有一个类层次结构,其中子类可以选择定义一个具有给定名称的方法,例如do_it
,并希望在基类中编写一个函数,例如do_all
,以确保每个这样的方法将按类层次结构的顺序执行。我能最接近实现这一点的是:
class A(object):
def do_it(self):
print 'Do A'
def do_all(self):
# Better, from comments and answers: vars(type(self))
for c in reversed(self.__class__.__mro__[:-1]):
c.do_it(self)
class B(A):
def do_it(self):
print 'Do B'
class C(B):
def no_do_it(self):
pass
class D(C):
def do_it(self):
print 'Do D'
这几乎可以按预期工作,例如B().do_all()
给出
Do A
Do B
但它会导致对B
do_it
的所有类的重复调用。例如D().do_all()
给出
Do A
Do B
Do B
Do D
如何避免未实现它的类对父do_it
的重复调用?这甚至是实现我想要做的事情的正确方法吗?
您可以检查是否已看到该函数:
def do_all(self):
seen = set()
for c in reversed(self.__class__.__mro__[:-1]):
if c.do_it not in seen:
seen.add(c.do_it)
c.do_it(self)
请注意,在 Python 2 中,您需要从未绑定方法中提取函数,如c.do_it.__func__
(或使用six.get_unbound_function
)。
另一种方法是检查__dict__
:
def do_all(self):
for c in reversed(self.__class__.__mro__[:-1]):
if 'do_it' in c.__dict__:
c.do_it(self)