python3 - super()对多继承的行为

时间:2014-06-11 14:58:11

标签: python inheritance python-3.x superclass super

我知道这里已经讨论过super()和多继承。但是我没有找到解决方案,关于我在python3中的具体问题。 我们假设我们有:

#! /usr/bin/env python3

class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(A,C):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

这会让我:

The
nice

另一方面,如果我将D()中的继承顺序更改为:

class D(C,A):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

它给了我

world
is
nice
但是,我只能获得所需的输出:

The
world
is
nice

使用:

class D(C,A):
    def __init__(self):
        super().__init__()

    def foo(self):
        A.foo(self)
        C.foo(self)
        print("nice")

我发现它非常不优雅。

所以我的问题是:是否可以在python3中使用super()来调用两个超类的超级方法而不仅仅是第一个?

2 个答案:

答案 0 :(得分:4)

不幸的是,如果不了解D的方法解析顺序(MRO),则无法在super()中调用D来获取两者基类。

但MRO是强大的概念。在第二种情况下,

class D(C,A):
    ...

(MRO)

>>> D.mro()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

正如调用super()将您带到MRO的下一个班级,正如Pieters先生所说,并且您希望打印语句按AB的顺序排列, C,然后是D,只需将super().foo()放在print(...)的每个定义中,然后foo()秒。唯一的例外是不要将super().foo()放在课程A中,因为foo()中未定义object

解决方案

#! /usr/bin/env python3

class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()      # Inserted
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(C,A):              # Correct ordering
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

替代解决方案

第一种情况下D(A,C)的MRO也包括所有类,因此正确排序super()print(...)语句,可以使其有效:

class A(object):
    def foo(self):
        print("The")
        super().foo()

class B(object):
    def foo(self):
        print("world")

class C(B):
    def foo(self):
        super().foo()
        print("is")

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

D().foo()

进一步阅读

要了解继承顺序(例如class D(C,A)class D(A,C))和MRO,请参阅https://www.python.org/download/releases/2.3/mro/。详细描述了C3方法的分辨率顺序,并且有很好的绘制的ASCII类层次结构,标有MRO。

答案 1 :(得分:2)

也许这会有所帮助

 class A(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("The")
        if hasattr(super(), 'foo'):
            super().foo()

class B(object):
    def __init__(self):
        super().__init__()

    def foo(self):
        print("world")

class C(B):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("is")

class D(A,C):
    def __init__(self):
        super().__init__()

    def foo(self):
        super().foo()
        print("nice")

d = D()

d.foo()

输出:

The
world
is
nice