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

Ric*_*ann 9 python inheritance super superclass python-3.x

我知道这里已经讨论过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()
Run Code Online (Sandbox Code Playgroud)

这会让我:

The
nice
Run Code Online (Sandbox Code Playgroud)

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

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

    def foo(self):
        super().foo()
        print("nice")
Run Code Online (Sandbox Code Playgroud)

它给了我

world
is
nice
Run Code Online (Sandbox Code Playgroud)

但是,我只获得所需的输出:

The
world
is
nice
Run Code Online (Sandbox Code Playgroud)

使用:

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

    def foo(self):
        A.foo(self)
        C.foo(self)
        print("nice")
Run Code Online (Sandbox Code Playgroud)

我发现它非常不优雅.

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

Jam*_*gle 4

不幸的是,如果不了解 的方法解析顺序 (MRO) D,就无法调用super()D获取这两个基类。

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

class D(C,A):
    ...
Run Code Online (Sandbox Code Playgroud)

(MRO) 是

>>> D.mro()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
Run Code Online (Sandbox Code Playgroud)

正如super()Pieters 先生所说,由于调用会将您带到 MRO 中的下一类,并且您希望打印语句按A, B, C, then 的顺序出现,因此只需将first 和secondaryD放入的每个定义中即可。唯一的例外是不要放入类中,因为未在 中定义。super().foo()print(...)foo()super().foo()Afoo()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()
Run Code Online (Sandbox Code Playgroud)

替代解决方案

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()
Run Code Online (Sandbox Code Playgroud)

进一步阅读

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