Python每日一题:MRO

题目:Python 中如何实现多继承?以及多继承会带来什么问题?

扩展题目:你了解 Python 中的 MRO 列表吗?

上篇文章,我们遗留了一个问题,就是 Python 中的多继承问题。今天进行详细介绍。首先看下昨天的代码:

正常按照我们学 JAVA 的思路(虽然 JAVA 里并不能同时 extends 两个类,但假定它即便把它看成是一个单一继承,输出也是不一样的),代码输出应该是:

之所以会出现这种结果,是因为在 Python 中有一个列表叫 MRO,它的全称是 Method Resolution Order,即方法解析顺序列表。对于我们定义的每个类,它都会根据一种特定的算法(C3线性算法,这里不作深入讨论)来得到一个列表,这个列表代表了类继承的顺序。我们可以通过 mro() 方法来查看某个类的 MRO 列表:

从结果我们可以看出,一个类的 MRO 列表会包含它所有父类的 MRO 列表,即父类的 MRO 列表其实是子类的一个真子集。而 super() 的执行就是根据这个列表而来的。下面让我们来仔细看下 super() 这个方法,它接受两个参数,第一个参数是当前子类的名称,第二个参数是 self ,它是一个固定参数,代表的是当前的实例对象。super() 执行的过程可以总结为两步:

根据我们传入的实例对象,通过 instance.__class__.mro() 得到当前类的 MRO 列表

根据列表的顺序,取列表的第二个元素,返回

这样就能解释之前的代码为什么会这样输出了。关键点在于我们是通过实例对象来获取到的 MRO 列表,而在整个继承的过程中,其实实例对象是没有发生改变的。它一直是类C的实例对象。这里用代码注释的形式给大家分解下步骤:

其实 super() 的调用过程,有点递归的味道。最后一个问题来了,为什么 Python 要设置一个 MRO 列表来规定继承中类的执行顺序呢?这是因为像我之前学过的 JAVA 语言,它是单继承的,一个属性方法的调用是十分明确的。而在 Python 中,是多继承的,如果父类中存在同名函数的时候,是会产生二义性的,MRO 就是用来处理这种问题的。它有三个原则:

子类一定在父类前面

如果存在多个父类,它会根据 MRO 列表顺序来执行

如果多个父类存在相同方法,会根据 MRO 列表选择第一个符合的类

愿关注我们的人都能找到

属于自己的皮球

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180317G1FYM500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券