super()的简单要点
super() 是一个内置函数,用于调用父类的方法。它的主要作用是:
- 访问父类:
super()可以让你轻松访问父类的方法,而不需要直接指定父类的名称。 - 方法解析顺序(MRO) :
super()依据调用顺序来查找方法。它遵循从当前类向上查找的规则,按照类的继承顺序。 - 支持多继承:在多继承情况下,
super()可以帮助处理方法的调用顺序,确保每个父类的方法都能被调用。
方法解析顺序(MRO, Method Resolution Order)是 Python 中确定方法调用顺序的规则,尤其在多继承的情况下。
MRO的简单要点
- 定义:MRO 是一个线性序列,表示查找方法时类的顺序。
- 优先级:从子类向上查找直到最顶层的父类,遵循类定义的顺序。
- 借助
super():使用super()时,会按照 MRO 查找父类的方法。 - 查看 MRO:可以使用
ClassName.__mro__或ClassName.mro()查看该类的 MRO。
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
print(D.__mro__)
输出
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
class Base(object):
def message(self, num):
print("base message", num)
super().message(10)
class Bar(object):
def message(self, num):
print("bar message",num)
class Foo(Base, Bar):
pass
obj = Foo()
obj.message(20)
输出:
base message 20
bar message 10
在这个例子中,你创建了一个继承自Base和Bar的类Foo。这两个基类都有名为message的方法。当你创建Foo类的一个对象并调用其message方法时,Python会首先查找Foo类中定义的message方法。如果没有找到,Python会查找Foo的基类(这里是Base和Bar)。在这个例子中,由于Foo类没有定义自己的message方法,所以Python会在Base类中查找这个方法并执行它。在Base类的message方法中,你调用了父类的message方法(通过super().message(10)),但由于Python会从最基类的位置开始向上查找方法,所以会执行到Bar类的message方法。因此,你会看到两行输出,首先是来自Base类的输出,然后是来自Bar类的输出。
这里有个问题: super().message(10)为什么会找到Bar类的message方法,而不是Base类的?
在 Python 中,super() 是根据方法解析顺序(MRO)查找方法的。以下是你代码中的 MRO: 1. Foo - 由于 Foo 继承自 Base 和 Bar,MRO 为 Foo -> Base -> Bar -> object。 当你在 Base 类中调用 super().message(10) 时,super() 会查找下一个方法,即 MRO 中的下一个类,结果是 Bar 类。因此调用 Bar 的 message 方法。 所以,Base 中的 super().message(10) 调用的是 Bar 类的 message 方法,而不是 Base 的,因为 super() 会依据 MRO 向下查找。