python3 - 多重继承中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()来调用两个父类的super方法,而不仅仅是第一个?
2 个回答
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
4
很遗憾,如果不知道 D
的方法解析顺序(MRO),就无法在 D
中调用 super()
来同时访问两个父类。
不过,MRO 是一个很重要的概念。在第二种情况下,
class D(C,A):
...
这个 (MRO) 是
>>> D.mro()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
正如 Pieters 先生所说,调用 super()
会让你进入 MRO 中的下一个类。如果你希望打印的顺序是 A
、B
、C
,然后是 D
,那么只需在每个 foo()
的定义中先写 super().foo()
,再写 print(...)
。唯一的例外是,不要在类 A
中写 super().foo()
,因为 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。