3

我有一个类层次结构,其中子类可以选择定义一个具有给定名称的方法,比如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

但它会导致对Bsdo_it的所有派生类的重复调用。例如D().do_all()给出

Do A
Do B
Do B
Do D

如何避免do_it从不实现它的类对父类的重复调用?这甚至是实现我想要做的事情的正确方法吗?

4

1 回答 1

4

您可以检查该功能是否已被看到:

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)
于 2014-01-07T18:43:30.297 回答