python学习之路---day20--面向对象--多继承和super() 函数


一:python多继承

 python多继承中,当一个类继承了多个父类时候,这个类拥有多个父类的所欲非私有的属性
    l例子:
        class A:
            pass
        class B(A):
            pass
        class C(A,B):
            pass
        B继承了A的属性,C继承了A和B的属性

:多继承中出现的问题:

    问题一:当一个类继承了多个父类,而这几个父类里面的方法名字写的一样,那该怎么办呢?

 例如:
        class A:
            def login(self):
                pass
        class B(A):
            def login(self):
                pass
        class C(A,B):
            def a(self):
                pass
这种情况下怎么去找呢? 这就涉及到了怎么查找父类的方法:
  MRO(method resolution order) 方法
    有两个查找版本:一个是python 2.2版本的经典类, 一个是python3版本后的C3算法
    经典版本MRO的查找原则,从左到右,先把左边的一条路找完,再回来继续找下一个(一条路走到黑)
新式的MRO查找原则:采用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的对象.
     如果从H找. 那找到H+H的⽗类的C3, 我们设C3算法是L(x) , 即给出x类. 找到x的MRO
     L(H) = H + L(G) + L(F)
     继续从代码中找G和F的父类往里面带
     L(G) = G + L(E)
     L(F) = F + L(D)+ L(E)
     继续找E 和 D
     L(E) = E + L(C) + L(A)
     L(D) = D + L(B) + L(C)
     继续找B和C
     L(B) = B + L(A)
     L(C) = C + L(A)
    最后就剩下⼀个A了. 也就不⽤再找了. 接下来. 把L(A) 往⾥带. 再推回去. 但要记住. 这⾥的
    + 表⽰的是merge. merge的原则是⽤每个元组的头⼀项和后⾯元组的除头⼀项外的其他元
    素进⾏比较, 看是否存在. 如果存在. 就从下⼀个元组的头⼀项继续找. 如果找不到. 就拿出来.
    作为merge的结果的⼀项. 以此类推. 直到元组之间的元素都相同. 也就不⽤再找了.

    L(B) =(B,) + (A,) -> (B, A)
    L(C) =(C,) + (A,) -> (C, A)
    继续带.
    L(E) = (E,) + (C, A) + (A) -> E, C, A
    L(D) = (D,) + (B, A) + (C, A) -> D, B, A
    继续带.
    L(G) = (G,) + (E, C, A) -> G, E, C, A
    L(F) = (F,) + (D, B, A) + (E, C, A) -> F, D, B, E, C, A
    最后:
    L(H) = (H,) + (G, E, C, A) + (F, D, B, E, C, A) -> H, G, F, D, B, E, C, A

    最终结果 HGFDBECA.   我们也可以用   类名.__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'>)

    总结:通过一层一层的先拆分,将原来的程序中的类按照它给的继承关系,列出如上诉的
    继承关系公式,然后再 用前一个的类(集合)的头和后面一个方法的 尾部(除去第一个类的后面、的类)
    对比,如果前面这个头的类名出现在了后面,那么这个头部的类名就去掉,继续这个类集合的下一个,如此循环
    直到找完就,最终得到一个 # L(H) = (H,) + (G, E, C, A) + (F, D, B, E, C, A) -> H, G, F, D, B, E, C, A
    这样的表达式,这就算是找完了。

    解释:C3算法: C3是把我们多个类产⽣的共同继承留到最后去找. 所以. 我们也可以从图上来看到相关
    的规律. 这个要⼤家⾃⼰多写多画图就能感觉到了. 但是如果没有所谓的共同继承关系. 那⼏乎就当成
    是深度遍历就可以了

三:super() 函数:

super()是查找mro顺序的下一个:单继承中我们可以认为super是对父类中的属性或则方法的引入

class ShengWu:
        def dong(self):
            print(self)
            print("生物")

    class Animal(ShengWu):
        pass
    class Cat(Animal):
        def dong(self): #子类中出现了和父类重名的内容,表示父类的方法的覆盖
            super().dong()  #定位到Animal 找Animal的下一个
            #super(类,对象).方法() 找到MRO中的类,找这个类的下一个,去执行方法
            print("猫会动")

    #找MRO中的下一个
    #Cat-->Animal--> ShengWu
    c=Cat()
    print(c)
    c.dong()
例子
MRO+super面试题
 class Init(object):
        def __init__(self, v):
            print("init")
            self.val = v # 2
    class Add2(Init):
        def __init__(self, val): # 2
            print("Add2")
            super(Add2, self).__init__(val)
            print(self.val) # 5.0
            self.val += 2 # 7.0
    class Mult(Init):
        def __init__(self, val):
            print("Mult")
            super(Mult, self).__init__(val)
            self.val *= 5 # 5.0
    class HaHa(Init):
        def __init__(self, val):
            print("哈哈")
            super(HaHa, self).__init__(val)
            self.val /= 5   # 1.0
    class Pro(Add2,Mult,HaHa): #
        pass
    class Incr(Pro):
        def __init__(self, val): # 5
            super(Incr, self).__init__(val)
            self.val += 1 # 8.0

    p = Incr(5)
    print(p.val)
    # Add2 init
    c = Add2(2)
    print(c.val)

    MRO算法后的顺序是(计算print(p.val)--> # Incr, pro, add2, mult, haha, Init(可以用print(Incr.__mro__)验证)
    print(p.val) 打印结果是: add2 Mult 哈哈  init  5.0   8.0
    print(c.val) 打印结果: Add2   init   2  4





原文地址:https://www.cnblogs.com/one-tom/p/9954977.html