Python基础13_类与类型, MRO, C3算法, super()

Posted 孤雁南飞123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础13_类与类型, MRO, C3算法, super()相关的知识,希望对你有一定的参考价值。

 一. python多继承  类与类型: http://www.cnblogs.com/blackmatrix/p/5594109.html
    子类继承了多个父类, 当父类出现了重名方法时, 这时就涉及到查找父类方法的问题, 即MRO(method resolution order)问题
    python中有两种类, 经典类和新式类
    在Python2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类,则称之为“经典类”。
    “新式类”和“经典类”的区分在Python3之后就已经不存在,在Python3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。
    主要是在多重继承时才会区分二者。

二. 经典类的MRO
    经典类的继承是深度优先遍历,即从下往上搜索;
    所有经典类的代码必须在Python2下运行
三. 新式类的MRO  官网C3算法解释: https://www.python.org/download/releases/2.3/mro/
    新式类的继承顺序是采用C3算法(非广度优先, 广度优先是按层级关系逐层遍历)
    方法中有super()才用得着MRO
    class A: 
        pass
    class B(A): 
        pass
    class C(A): 
        pass
    class D(B, C): 
        pass
    class E(C, A): 
        pass
    class F(D, E): 
        pass
    class G(E): 
        pass
    class H(G, F): 
        pass
    (1).分拆
    首先. 我们要确定从H开始找. 也就是说. 创建的是H的对象.
    如果从H找. 那找到H的父类的C3, 我们设C3算法是L(x) , 即给出x类. 找到x的MRO 
     L(H) = H + L(G) + L(F) + GF
    继续从代码中找G和F的父类往里面带
     L(G) = G + L(E) + E
     L(F) = F + L(D)+ L(E) + DE
    继续找E 和 D
     L(E) = E + L(C) + L(A) + CA
     L(D) = D + L(B) + L(C) + BC
    继续找B和C
     L(B) = B + L(A) + A
     L(C) = C + L(A) + A
    (2).合并
    最后就剩下⼀一个A了了. 也就不用再找了了. 接下来. 把L(A) 往里带. 再推回去. 但要记住. 这里的 + 表示的是merge. merge的原则是用每个元组的头⼀一项和后面元组的除头一项外的其他元素进行比较, 看是否存在. 如果存在. 就从下一个元组的头一项继续找. 如果找不到. 就拿出来. 作为merge的结果的一项. 以此类推. 直到元组之间的元素都相同. 也就不用再找了了.
     L(B) =(B,) + (A,) + (A) -> (B, A)
     L(C) =(C,) + (A,) + (A) -> (C, A)
    继续带.
     L(E) = (E,) + (C, A) + (A) + (C,A) -> E, C, A
     L(D) = (D,) + (B, A) + (C, A) + (B, C) -> D, B, C, A
     继续带.
     L(G) = (G,) + (E, C, A) + (E) -> G, E, C, A
     L(F) = (F,) + (D, B, C, A) + (E, C, A) + (D, E)-> F, D, B, E, C, A
     加油, 最后了
     L(H) = (H, ) + (G, E, C, A) + ( F, D, B, E, C, A) + (G, F) -> H, G, F, D, B, E, C, A
     算完了. 最终结果 HGFDBECA. 那这个算完了. 如何验证呢? 其实python早就给你准备好了. 我们可以使用类名.__mro__获取到类的MRO信息.
     print(H.__mro__)
    结果:
    (<class \'__main__.H\'>, <class \'__main__.G\'>, <class \'__main__.F\'>, <class \'__main__.D\'>, <class \'__main__.B\'>, <class \'__main__.E\'>, <class \'__main__.C\'>,<class \'__main__.A\'>, <class \'object\'>)
    结果OK. 那既然python提供了. 为什么我们还要如此麻烦的计算MRO呢? 因为笔试.......你在笔试的时候, 是没有电脑的. 所以这个算法要知道. 并且简单的计算要会. 真是项⽬开发的时候很少有人这么去写代码.
四. super()
    super()帮我们执行MRO中下一个父类的方法, 通常super()有两个使用的地方
    1. 可以访问父类的构造方法, 简化了子类的书写
    2. 当子类方法想调用父类MRO中的方法
    super(cls, self).func() 执行cls类的MRO中下一个类的func方法
    super().func()    执行当前类的MRO中下一个类的func方法

以上是关于Python基础13_类与类型, MRO, C3算法, super()的主要内容,如果未能解决你的问题,请参考以下文章

python的MRO和C3算法

16 继承 MRO和C3算法

python 面向对象MRO C3算法 super

多继承c3算法与网路编程

mro之C3算法

Python的多继承问题-MRO和C3算法