我有一个类层次结构,其中子类可以选择性地定义具有给定名称的方法,比如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
s do_it
的重复调用。例如D().do_all()
给出
Do A
Do B
Do B
Do D
如何避免从未实现父类do_it
的类中重复调用?这甚至是实现我想要做的事情的正确方法吗?
答案 0 :(得分:3)
您可以检查是否已经看到该功能:
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)