Python:多重继承问题

>>最全面的Java面试大纲及答案解析(建议收藏)  

本机环境:Ubuntu 16.04 LTS
Python3.5

MRO 方法解析顺序

作为一个面向对象的语言,python支持多重继承,但是当父类存在同名方法时,继承关系就会给人带来困惑了。这时候我们引入了MRO(Method Resolution Order):方法解析顺序这个概念。我们可以使用__mro__来查询继承顺序,如classA.__mro__。在python3中,MRO基于C3算法

C3算法

MRO是一个有序列表L,在类被创建时就计算出来。C3算法的表达式如下:

L[C(A,B)]= D + merge(L[A],L[B],[A,B])

merge的操作如下:

merge: ① 若列表为空则结束,非空则读merge中第一个列表的表头,
              ② 查看该表头是否在 merge中所有列表的表尾中。
              ②-->③ 不在,则放入最终的L中,并从merge中的所有列表中删除,然后 回到①
              ②-->④ 在,查看当前列表是否是merge中的最后一个列表
              ④-->⑤ 不是 ,跳过当前列表,读merge中下一个列表的表头,然后回到②
              ④-->⑥ 是,异常。类定义失败。

表头即列表中第一个元素,表尾为除表头外元素的集合(允许为空)
通过C3算法的运算,我们可以得到在多重继承中类的继承顺序。

拓扑排序

C3算法的运算过程看起来有些复杂,其实我们还可以用图论中的对一个有向无环图拓扑排序来解决这个问题。列举一个拓扑排序的方法:

  • 从DAG途中选择一个没有前驱(即入度为0)的顶点并输出。

  • 从图中删除该顶点和所有以它为起点的有向边。

  • 重复1和2直到当前DAG图为空或当前途中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。
    举例如下:

class E(object):
   pass
class D(object):
   pass
class C(E):
   pass
class B(D):
   pass
class A(B, C):
   pass

我们可以画图(没找到合适的画图工具=-=):

Python:多重继承问题

  • 第一个入度为0的点是A,取出A,并除去相关边。

  • B在左边,先取出B,操作同上

  • 剩下D和C都是入度为0,但D在左,取D

  • C入度为0,取C

  • 接着取E,最后剩下object
    可得继承顺序为L=[A,B,D,C,E,object]



原文始发于微信公众号(公子政的宅日常):Python:多重继承问题