一 基础使用

  在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如:

 #!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# Author:taoke class baseClass(object):
def __init__(self):
print("baseClass______in")
print("baseClass______out") class A(baseClass):
def __init__(self):
print("A_____________in")
super(A,self).__init__()
print("A_____________out") if __name__ == "__main__":
a = A()

运行结果:

 A_____________in
baseClass______in
baseClass______out
A_____________out

二 深入使用

  看了上面的使用,你可能会觉得 super 的使用很简单,无非就是获取了父类,并调用父类的方法。其实,在上面的情况下,super 获得的类刚好是父类,但在其他情况就不一定了,super 其实和父类没有实质性的关联

让我们看一个稍微复杂的例子,涉及到多重继承,代码如下:

 #!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# Author:taoke class baseClass(object):
def __init__(self):
print("baseClass_____in")
print("baseClass_____out") class A(baseClass):
def __init__(self):
print("A_____________in")
super(A,self).__init__()
print("A_____________out") class B(baseClass):
def __init__(self):
print("B_____________in")
super(B, self).__init__()
print("B_____________out") class C(A,B):
def __init__(self):
print("C_____________in")
super(C,self).__init__()
print("C_____________out") if __name__ == "__main__":
t = C()

运行结果:

 C_____________in
A_____________in
B_____________in
baseClass_____in
baseClass_____out
B_____________out
A_____________out
C_____________out

其中,baseClass 是父类,A, B 继承自 baseClass, C 继承自 A, B,它们的继承关系如下:

   baseClass
/ \
/ \
A B
\ /
\ /
C

如果你认为 super 代表『调用父类的方法』,那你很可能会疑惑为什么 A_____________in 的下一句不是baseClass_____in而是 B_____________in。原因是,super 和父类没有实质性的关联,现在让我们搞清 super 是怎么运作的。

三 MRO 列表

  事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表:

 print(C.mro())

运行结果:

 [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.baseClass'>, <class 'object'>]

那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

  1.子类永远在父类前面

  2.如果有多个父类,会根据它们在列表中的顺序被检查

  3.如果对下一个类存在两个合法的选择,选择第一个父类

四 super原理

  super 的工作原理如下:

 def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]

其中,cls 代表类,inst 代表实例,上面的代码做了两件事:

  • 获取 inst 的 MRO 列表
  • 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]

当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。

回到前面的例子,根据[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.baseClass'>, <class 'object'>]

运行顺序为:

 C
{
print("C_____________in")
  A
  {
print("A_____________in")
    B
    {
print("B_____________in")
      baseClass
      {
        print("baseClass_____in")
print("baseClass_____out")
      }
print("B_____________out")
    }
print("A_____________out")
  }
print("C_____________out")
}

整个过程还是比较清晰的,关键是要理解 super 的工作方式,而不是想当然地认为 super 调用了父类的方法。

小结:

  • 事实上,super 和父类没有实质性的关联。
  • super(cls, inst) 获得的是 cls 在 inst 的 MRO 列表中的下一个类。
 

Python super使用的更多相关文章

  1. Python ---- super()使用

    Python ---- super() 我们经常在类的继承当中使用super(), 来调用父类中的方法.例如下面: 1 2 3 4 5 6 7 8 9 10 11 12 13 class A:     ...

  2. Python super继承详解

    MRO(Method resolution order)是python用来解析方法调用顺序的,mro中记录了一个类的所有基类的类类型序列,super不是简单地调用基类的方法,而是按照MRO中的顺序来调 ...

  3. python super

    http://hi.baidu.com/thinkinginlamp/item/3095e2f52c642516ce9f32d5 Python中对象方法的定义很怪异,第一个参数一般都命名为self(相 ...

  4. python super参数错误

    # -*- coding:utf-8 _*-"""@author:Administrator@file: yamlparser.py@time: 2018/09/07&q ...

  5. python super超类方法

    super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重复调用( ...

  6. Python super() 函数的概念和例子

    概念: super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重 ...

  7. python: super原理

    super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: ...

  8. python super()函数

    super()函数是用来调用父类(超类)的一个方法 super()的语法: python 2 的用法: super(Class, self).xxx  # class是子类的名称 class A(ob ...

  9. (转)Python: super 没那么简单

    原文:https://mozillazg.com/2016/12/python-super-is-not-as-simple-as-you-thought.html python 约定¶ 单继承¶ 多 ...

随机推荐

  1. 一周总结:AutoEncoder、Inception 、模型搭建及下周计划

    一周总结:AutoEncoder.Inception .模型搭建及下周计划   1.AutoEncoder: AutoEncoder: 自动编码器就是一种尽可能复现输入信号的神经网络:自动编码器必须捕 ...

  2. 使用jmeter+ant进行接口自动化测试(数据驱动)之一:设计jmeter脚本

    最近在做接口测试,因为公司有使用jmeter做接口测试的相关培训资料,所以还是先选择使用jmeter来批量管理接口,进行自动化测试.话不多说,进入正题: 1.使用csv文件保存接口测试用例,方便后期对 ...

  3. Python 线程复习

    修改全局变量,设立flag来避免线程间数据冲突,低效率版 from threading import Thread import time g_num=0 g_flag = 1 def test1() ...

  4. 【iOS】swift-文字宽度的计算

    如图所示,需要sectionView的标题宽度可以动态变化 举例说明: 只需在tableView的代理方法 func tableView(tableView: UITableView, viewFor ...

  5. JVM启动参数

    JVM参数的含义 实例见实例分析 参数名称 含义 默认值   -Xms 初始堆大小 物理内存的1/64(<1GB) 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,J ...

  6. BM V7000数据恢复成功案例;服务器数据恢复

    IBM V7000存储是一款定位中端的存储设备,很多企业选择该服务器作为存储,最近北亚数据恢复中心接到一例V7000服务器数据恢复案例,下面将对本次数据恢复的过程和数据恢复方法进行归纳总结,希望对各位 ...

  7. JAVA_SE基础——16.方法

    接触过C语言的同学,这小章节很容易接受.Java中的方法是类似与C语言中的函数  功能和调用方法都类似  只不过叫法不一样  因为java是面向对象  c是面向过程    仅仅是叫法不同.. . 看到 ...

  8. java语法基础(总结)

    1,关键字:其实就是某种语言赋予了特殊含义的单词. 保留字:其实就是还没有赋予特殊含义,但是准备日后要使用过的单词. 2,标示符:其实就是在程序中自定义的名词.比如类名,变量名,函数名.包含 0-9. ...

  9. 在thinkphp框架中使用后台传值过来的数组,在hightcart中使用数组

    js的数组是和php里面数组是不一样的,所以模板文件需要先接受,然后利用Js代码转化之后再使用,接受后台的数组有几种办法 1.后台传过来的json数组,利用Js是可以接受的,然后将json数据利用js ...

  10. JavaScript-Jquery实现全选反选

    html: <dl> <dt><input type="checkbox" id="checkAll" /><labe ...