Python调用父方法多重继承

问题描述 投票:11回答:3

所以,我有这样的情况。

class A(object):
    def foo(self, call_from):
        print "foo from A, call from %s" % call_from


class B(object):
    def foo(self, call_from):
        print "foo from B, call from %s" % call_from


class C(object):
    def foo(self, call_from):
        print "foo from C, call from %s" % call_from


class D(A, B, C):
    def foo(self):
        print "foo from D"
        super(D, self).foo("D")

d = D()
d.foo()

代码的结果是

foo from D
foo from A, call from D

我想调用所有父方法,在本例中为foo方法,来自D类,而不使用像A这样的父类。我只想打电话给D班的超级。 ABC类就像mixin类,我想从D调用所有foo方法。我怎样才能实现这一目标?

python class inheritance multiple-inheritance
3个回答
8
投票

你可以像这样使用__bases__

class D(A, B, C):
    def foo(self):
        print "foo from D"
        for cls in D.__bases__:
            cls().foo("D")

通过此更改,输出将是

foo from D
foo from A, call from D
foo from B, call from D
foo from C, call from D

9
投票

除了super()之外,还可以在其他类中添加C调用。因为D的MRO是

>>> D.__mro__
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>)

你不需要在C超级电话。

码:

class A(object):
    def foo(self, call_from):
        print "foo from A, call from %s" % call_from
        super(A,self).foo('A')

class B(object):
    def foo(self, call_from):
        print "foo from B, call from %s" % call_from
        super(B, self).foo('B')


class C(object):
    def foo(self, call_from):
        print "foo from C, call from %s" % call_from

class D(A, B, C):
    def foo(self):
        print "foo from D"
        super(D, self).foo("D")

d = D()
d.foo()

输出:

foo from D
foo from A, call from D
foo from B, call from A
foo from C, call from B

0
投票

我相信在子类中调用super更像是Pythonic方法。一个人不必使用父类名(特别是在super中)。在前面的例子中详细说明,这里有一些应该工作的代码(python 3.6+):

class A:
    def foo(self, call_from):
        print(f"foo from A, call from {call_from}")
        super().foo('A')

class B:
    def foo(self, call_from):
        print(f"foo from B, call from {call_from}")
        super().foo('B')


class C(object):
    def foo(self, call_from):
        print(f"foo from C, call from {call_from}")
        super().foo('C')

class StopFoo:
    def foo(self, call_from):
        pass

class D(A, B, C, StopFoo):
    def foo(self, call_from):
        print(f"foo from D, call from {call_from}")
        super().foo('D')

如果您运行此代码:

d = D()
d.foo('D')

你会得到:

foo from D, call from D
foo from A, call from D
foo from B, call from A
foo from C, call from B

这个策略的优点是你不必担心继承顺序,因为你包含了StopFoo类。这个有点特殊,可能不是完成这项任务的最佳策略。基本上,继承树中的每个类都调用foo方法并调用父方法,该方法也是如此。我们可能在谈论多重继承,但是继承树实际上是平的(D - > A - > B - > C - > Stopfoo - > object)。我们可以改变继承的顺序,为这个模式添加新类,删除它们,只需调用一个类......但诀窍仍然存在:在调用StopFoo之前包含foo会离开我们定义的类。

对于带钩子的mixin图案,这可能有意义。但是,当然,解决方案在每种情况下都没有那么有用。不要害怕super,它有很多技巧,可以用于简单和多重继承,使用mixins或简单的抽象类。

© www.soinside.com 2019 - 2024. All rights reserved.