zoukankan      html  css  js  c++  java
  • python单继承与多继承

    一、单继承

    子类调用父类的一个方法,可以用super():

    class A(object):
        def pp(self):
          print('pp A')
    
    class B(A):
        def pp(self):
          super().pp()
          print("pp B")
    
    b = B()
    b.pp()
    
    #结果:
    pp A
    pp B

    super()常用的方法是在__init__()方法中确保父类被正确的初始化了:

    super(cls,inst).__init__() #cls,init 可以省略

    class A(object):
        def __init__(self):
          self.x = 1
    
    class B(A):
        def __init__(self):
          super(B,self).__init__()
          self.x = self.x +1
          print(self.x)
    
    b = B()
    
    #结果
    2

    也可以直接调用父类的一个方法 :

    A.__init__(self)
    class A(object):
        def __init__(self):
            self.x = 1
    
    class B(A):
        def __init__(self):
            A.__init__(self)
            self.x = self.x +1
            print(self.x)
    b = B()
    
    #结果
    2                    

    二、多继承

    super().xx方法可以理解为调用了父类中的方法xx,但是其实在单继承中是这样,而多继承中有些区别

    如下:

    class A(object):
        def __init__(self):
            print("Enter A")
    
    class B(A):
        def __init__(self):
            print('Enter B')
            super(B,self).__init__()
            print('Leave B')
    
    class C(A):
        def __init__(self):
            print('Enter C')
            super(C, self).__init__()
            print('Leave C')
    
    class D(B,C):
        def __init__(self):
            print('Enter D')
            super(D,self).__init__()
            print("Leave D")
    
    d = D()
    结果为:
    
    Enter D
    Enter B
    Enter C
    Enter A
    Leave C
    Leave B
    Leave D                                            

    如果按照原本的理解,是调用了B,C类中的方法,结果不会是这样,那么为什么会这样呢?

    其实是我们理解错了super()

    super()的用法:

    1.super()的本质

      先说说python中如何实现继承---------对于你定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就是一个简单的所有基类的线性顺序表。为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。

    而这个MRO列表的构造是通过一个C3线性化算法来实现的。 我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

    子类会先于父类被检查
    多个父类会根据它们在列表中的顺序被检查
    如果对下一个类存在两个合法的选择,选择第一个父类
    虽然名义上来说super是用来调用父类中的方法,但是super实际上是在MRO表中找到下一个匹配的类。super原型如下:

    def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]
    两个参数 cls 和 inst 分别做了两件事:
    1. inst 负责生成 MRO 的 list
    2. 通过 cls 定位当前 MRO 中的 index, 并返回 mro[index + 1]

    但是根据我们上面说的super本质知道 super 和父类其实没有实质关联,我们就不难理解为什么 enter B 下一句是 enter C 而不是 enter A了(如果认为 super 代表“调用父类的方法”,会想当然的认为下一句应该是enter A)。

    可以用  self.__class__.__mro__ 方法来查询当前MRO

    MRO:

    (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
    在我的理解里,一个多继承中的ORM是固定的(只要每个类之间都有继承关系)

    上方例子的中流程:

    首先是class D中,输出“Enter D" , 然后就会调用super方法,super()方法,第一个参数是D,在MRO列表中的下标(index)为0,那么调用的下一个类就是下标为(index+1)的类,即class B,

    那么进入class B,输出"Enter B" ,再次调用super(),此时的index为1,那么调用的下一个类的index为2,即class C,输出“Enter C” , 然后在class C中,调用super(),进入class A,输出“Enter A”,然后回到class C ,输出 "Leave C" , 再回到class B ,输出“Leave B”, 然后回到class D,输出“Leave D”。结束

    当你使用 super() 函数时,Python会在MRO列表上继续搜索下一个类。 只要每个重定义的方法统一使用 super() 并只调用它一次, 那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次。

  • 相关阅读:
    Power BI 根据用户权限动态生成导航跳转目标
    Power BI Tooltips 增强功能
    Power BI refresh error “could not load file or assembly…provided impersonation level is invalid”
    SQL 错误代码 18456
    如何使用SQL Server Integration Services从多个Excel文件读取数据
    通过表格编辑器将现有表引入Power BI数据流
    Power BI 中动态增长的柱状图
    ambari2.7.3离线安装hdp3.1.0时,ambari-hdp-1.repo中baseurl无值
    ambari 安装 cannot download file mysql-connector-java from http://8080/resource/mysql-connector-java.jar
    洛谷P4180 [BJWC2010]严格次小生成树
  • 原文地址:https://www.cnblogs.com/lnd-blog/p/11763873.html
Copyright © 2011-2022 走看看