3.3.2 Python 的多继承
Python 语法直接支持多继承:
这就是著名的菱形问题,D 继承自 B 和 C,而 B 和 C 都继承自 A,他们的继承关系构成一个菱形。调用 D 类实例的 foo
方法会让人产生疑惑,它的父类们都实现了 foo
方法,到底以谁为准?
Python 有一套算法来计算遍历顺序,这个顺序叫做方法解析顺序(Method Resolution Oder,MRO)。这个算法叫做 C3 算法,可以参考这篇官方文档:The Python 2.3 Method Resolution Order
不过绝大多数情况下,除非你的代码极度依赖多继承,否则都不需要了解这个算法的具体工作原理。一方面,我们可以调用某个特定父类的方法。我们也许已经注意到两个事实,首先类中定义的方法其实都是类的属性,但调用者都是类的实例。其次,类方法的第一个参数都是 self
,表示方法的调用者,但我们调用时并不需要传入实例。这是因为其实实例方法的正规调用方式是这样的:
这种调用方式符合定义,而且能够解释上述的两个疑问。然而这种调用方式不仅写起来麻烦,还很不合理,因为我们不仅要实例对象,还需这个实例所属的类才能调用。因此,Python 的做法是将类中定义的方法绑定到每一个实例上:
可以清楚的从 d.foo
的输出结果看出来,它是绑定到 d
对象上的函数,第一个参数 self
就是d
。
另一方面,我们不仅可以调用任意父类的方法,还可以通过类的 __mro__
属性查看父类的继承顺序:
所以,多继承的方法调用顺序一般情况下不会对开发代码造成太大的困扰。
Last updated