zoukankan      html  css  js  c++  java
  • python super()

    super()入门级用法还是比较简单的.

    在类的继承当中,如果要在子类中重写某个父类同名方法,该方法会覆盖父类的同名方法;但是,有的时候,我们在重写父类方法时,同时也要调用父类同名方法功能.这时,

    我们可以通过使用super()方法来实现.比如:

     1 class Father:
     2     def __init__(self):
     3         print("Father.__init__")
     4 
     5 
     6 class Son(Father):
     7     def __init__(self):
     8         Father.__init__(self)       ##这种方法不推荐使用
     9         super(Son, self).__init__() ##主流用法
    10         super().__init__()          ##python3 支持这个写法
    11         print("Son.__init__")
    12 
    13 
    14 s = Son()
    15 
    16 结果:
    17 Father.__init__
    18 Father.__init__
    19 Father.__init__
    20 Son.__init__

    在上面,Father是父类,Son是子类,我们在Son中重定义了__init__()函数,但同时也想执行父类[Father]类的__init__方法,我们使用了super(),

    super()有三种方法.主流方法是第二种...

    深入了解super()

    从上面的例子的示范,可能觉得super()的使用很简单,无非就是在重写父类的同时,调用父类的方法..其实,在上面的例子中,super()获得的类刚好是父类,

    在其他的一些情况下就不一定了,super其实和父类没有任何实质性的联系.

    一个复杂的例子,涉及到python 类的多重继承,我使用的是python3.

     1 class Base:
     2     def __init__(self):
     3         print("enter Base")
     4         print("leave Base")
     5 
     6 
     7 class A(Base):
     8     def __init__(self):
     9         print("enter A")
    10         super().__init__()
    11         print("leave A")
    12 
    13 
    14 class B(Base):
    15     def __init__(self):
    16         print("enter B")
    17         super().__init__()
    18         print("leave B")
    19 
    20 
    21 class C(A, B):
    22     def __init__(self):
    23         print("enter C")
    24         super().__init__()
    25         print("enter C")
    26 
    27 
    28 c = C()

    其中,Base是父类,A,B继承自Base,C继承A,B,继承关系图

        Base
        /  
       /    
      A      B
           /
          /
         C

    代码执行结果:

    1 enter C
    2 enter A
    3 enter B
    4 enter Base
    5 leave Base
    6 leave B
    7 leave A
    8 enter C
    View Code

    看了结果,是不是和你想的有点不一样?你想的是不是,enter A的下一句enter Base?

    这里的结果和我们所认为的有所差别.原因在于,super和父类是没有实质性的联系.下面让我们看看,super在程序中道理是如何运行的!

    MRO列表

    python的类继承,在我们每定义一个类,都会计算出一个方法解析顺序(Method Reselution Order,MRO)列表.我们可以使用下面的方式获得一个类的MRO列表.

    print(C.mro())
    [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

    一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

    • 子类永远在父类前面
    • 如果有多个父类,会根据它们在列表中的顺序被检查
    • 如果对下一个类存在两个合法的选择,选择第一个父类

    super原理

    接上面代码后面

     1 def super(cls, inst):
     2     """
     3     1.获取inst的MRO列表
     4     2.查找cls在当前MRO列表中的index,并返回它的下一个类,即mro[index + 1]
     5     总结:当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。
     6     :param cls: 代表类
     7     :param inst: 代表实例
     8     :return:
     9     """
    10     mro = inst.__class__.mro()
    11     return mro[mro.index(cls) + 1]
    12 ret = super(C,c)
    13 print(ret)
    14 结果:<class '__main__.A'>

    好了,让我们回到之前的例子:

    super(C,self).__init()

    这里的self是当前C的实例,self.class.mro()结果:

    1 [__main__.C, __main__.A, __main__.B, __main__.Base, object]

    可以看出,C的下一个类是A,于是,跳到了A的__init__.这是会打印enter A,执行下一句

    super(A,self).__init__()

    注意,这里的 self 也是当前 C 的实例,MRO 列表跟上面是一样的,搜索 A 在 MRO 中的下一个类,发现是 B,于是,跳到了 B 的 __init__,这时会打印出 enter B,而不是 enter Base。

    =.=

    人生苦短,我用python!
  • 相关阅读:
    2019牛客暑期多校训练营(第二场)H Second Large Rectangle
    HDU -1506 Largest Rectangle in a Histogram&&51nod 1158 全是1的最大子矩阵 (单调栈)
    吉哥系列故事——完美队形II(马拉车算法)
    Theme Section
    激光雷达和毫米波雷达
    模型压缩95%:Lite Transformer,MIT韩松等人
    分布式深度学习DDL解析
    TOF摄像机可以替代Flash激光雷达吗?
    毫米波雷达分类和技术方案
    高精地图与自动驾驶(下)
  • 原文地址:https://www.cnblogs.com/xu-rui/p/6482986.html
Copyright © 2011-2022 走看看