zoukankan      html  css  js  c++  java
  • 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
    
    
    



  • 相关阅读:
    回顾:异常处理,值传递和引用传递
    回顾:静态变量和实例变量、构造器
    多态、抽象类与接口
    回顾:面向对象、基本类型
    总结一下《深入理解Java虚拟机》
    百度实习生面试题
    面试题
    阿里面试
    Shell
    Collector详解
  • 原文地址:https://www.cnblogs.com/one-tom/p/9954977.html
Copyright © 2011-2022 走看看