问题 Python调用父方法多重继承


所以,我有这样的情况。

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 没有在父类中使用super的类 A。我只想打电话给超级 D 类。该 AB,和 C class就像mixin类一样,我想调用所有foo方法 D。我怎样才能做到这一点?


10265
2017-12-08 07:23


起源



答案:


您可以使用 __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

8
2017-12-08 07:46



这有点粗略......如果你现在有两个类都继承自D,然后是另一个继承自这两个类的类呢?现在 foo 将会通知 A.foo 两次。 - mgilson
或者如果发生了什么 B.foo 不存在?最后,我认为应该如此 cls.foo(self)不是 cls().foo() - mgilson
@mgilson然后,我们必须使用 mro?那些不是阶级方法,对吗?所以,我必须创建对象来调用它们。 - thefourtheye
它们不是类方法,但如果明确传递,则可以从类中调用该方法 self 作为第一个参数(和 self 是正确的类型)。 - mgilson
在这种情况下,我们没有问题 self,但在他的实际代码中,他可能会变异 self 这会产生问题。所以,我相信,最好这样称呼它 - thefourtheye


答案:


您可以使用 __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

8
2017-12-08 07:46



这有点粗略......如果你现在有两个类都继承自D,然后是另一个继承自这两个类的类呢?现在 foo 将会通知 A.foo 两次。 - mgilson
或者如果发生了什么 B.foo 不存在?最后,我认为应该如此 cls.foo(self)不是 cls().foo() - mgilson
@mgilson然后,我们必须使用 mro?那些不是阶级方法,对吗?所以,我必须创建对象来调用它们。 - thefourtheye
它们不是类方法,但如果明确传递,则可以从类中调用该方法 self 作为第一个参数(和 self 是正确的类型)。 - mgilson
在这种情况下,我们没有问题 self,但在他的实际代码中,他可能会变异 self 这会产生问题。所以,我相信,最好这样称呼它 - thefourtheye


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

8
2017-12-08 07:33



如果您不理解我的描述,我想打电话给所有人 foo 没有在父类调用super的方法 A 要么 B 要么 C。 - Edwin Lunando
@EdwinLunando - 我相信这不是怎么回事。为了使super能够正常工作,所有类都需要使用它。 请参阅有关将超级方法与非超级方法混合的部分。 - mgilson
@EdwinLunando然后迭代 __mro__, 要么 __bases__ 并明确地调用每个类,但接着你 不能用  super 在 D。 - Ashwini Chaudhary
此解决方案错误,因为现在正在调用 A().foo() 要么 B().foo() 会引发例外。您现在只能使用派生类中的这些类,这些类也派生自 C (或类似的类),顺序也变得重要(C 必须是最后的)。为了使其正常工作,您需要从实现的基类派生所有类 foo。 - interjay