• day21 MRO和C3算法


    核能来袭 --MRO和C3算法

    1. python的多继承 

    2.python经典类的MRO

    3.python新式类的MRO, C3算法

    4.super 是什么鬼?

    一.python的多继承

    在前面的学习过程中,我们已经知道了python中类与类之间可以有继承关系,当出现了x是一种y的时候,局可以使用继承关系.在继承关系中,子类自动拥有父类除了私有属性外的其他所有的内容,python支持多继承.一个类可以拥有多个父类.

    class ShenXian: #神仙
        def fei(self):
            print('神仙都会飞')
    
    class Monkey: #猴
        def chitao(self):
            print('猴子喜欢吃桃子')
    
    class WuKong(shenxian,Monkey): # 孙悟空
        pass
    
    qtds=WuKong() #齐天大圣
    qtds.chitao() # 吃桃
    qtds.fei() # 飞
    

    多继承用起来很简单,也很好理解,但是如果2个父类中出现重名方法时,这时就出现了查找顺序的问题,即MRO问题:

    在python2中存在2 类,经典类,新式类(注意:树形结构图和C3算法算出来的结果不一定是相同的)

      经典类:在python2.2之前,一直使用的是经典类,经典类在基类的根如果什么都不写,表示继承xxx

      新式类:在python2.2之后出现了新式类,特点是基类的根是object

    在python3中,

      都是新式类,如果基类谁都不继承,那么这个类默认继承object

    二 . python经典类的MRO

    虽然python3中不存在经典类了,但还是要学一学,经典类是一种树形结构遍历的一个最直接的案例,在python继承体系中,我们可以把类与类继承关系化成一个树形结构图,

    class A:
        pass
    class B(A):
        pass
    class C(A):
        pass
    class D(B, C):
        pass
    class E:
        pass
    class F(D, E):
        pass
    class G(F, D):
        pass
    class H:
        pass
    class Foo(H, G):
        pass
    

    碰到这样的代码的时候,不要急,画树形结构图(从下往上画)这里就不列举了  

    结果,类的MRO: Foo-> H -> G -> F -> D -> B -> A -> C -> E. 

     三.新式类的MRO

    Python个中的新式类的MRO是采用C3算法来完成的

    C3算法其实很简单,只要看代码就可以了,不需要去画图,

    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
    

     首先我们要确定从H开始找:(从下往上找),也就是说,创建的是H的对象.

    设C3算法是L(x),找到x对的MRO,即:

    L(H)=H+L(G)+L(F)+GF

    继续从父类中往上找

    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

    (注:加法,merge(),拿第一项的第一位与后面每项中除了第一位比较,如果没出现,算出这一位(算出后所有的这一个字母全部删除),继续拿这一位的下一位重复上面的操作;如果出现了,此时开始下一项的第一位继续跟后面每一项的出了第一位比较)  

    这个说完了,C3到底怎么看更容易呢,其实很简单,C3是把我们多个类产生的共同继承留到最后去找,所以,我们也可以从图上来看到相关的规律,这个要大家自己多写多画就能感觉到了,但是如果没有所谓的共同继承关系,那几乎就当成是深度遍历就可以了.

    四.super是什么鬼?

    super()可以帮我们执行MRO中下一个父类的方法,通常super()有两个使用的地方

    1)可以访问父类的构造方法

    2) 当子类方法想调用父类(MRO)中的方法

    # MRO + super 面试题
    class Init(object):
        def __init__(self, v):
            print("init")
            self.val = v
    class Add2(Init):
        def __init__(self, val):
            print("Add2")
            super(Add2, self).__init__(val)
            print(self.val)
            self.val += 2
    class Mult(Init):
        def __init__(self, val):    
            print("Mult")
            super(Mult, self).__init__(val)
            self.val *= 5
    class HaHa(Init):
        def __init__(self, val):
            print("哈哈")
            super(HaHa, self).__init__(val)
            self.val /= 5
    class Pro(Add2,Mult,HaHa): #
        pass
    class Incr(Pro):
        def __init__(self, val):
            super(Incr, self).__init__(val)
            self.val+= 1
    # Incr Pro Add2 Mult HaHa Init
    p = Incr(5)
    print(p.val)
    c = Add2(2)
    print(c.val)
    

    结论: 不管super()写在哪里,在哪执行.一定先找到MRO列表,根据MRO列表的顺序往下找,否则一切都是错的 

  • 相关阅读:
    mysql/mariadb基于ssl的主从复制
    原创工具binlog2sql:从MySQL binlog得到你要的SQL
    [转]MySQL DBA面试全揭秘
    mysql my.cnf 配置建议
    mysql配置文件 /etc/my.cnf 详细解释
    [转]expect实现ssh自动交互
    Linux中的lo回环接口详细介绍
    Docker最全教程——从理论到实战(五)
    Docker最全教程——从理论到实战(四)
    Docker最全教程——从理论到实战(一)
  • 原文地址:https://www.cnblogs.com/zty1304368100/p/10169159.html
Copyright © 2020-2023  润新知