super的入门使用:

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

class Animal(object):
def __init__(self, name):
self.name = name def greet(self):
print(self.name) class Dog(Animal):
def greet(self):
super(Dog, self).greet()
print('wang wang') obj = Dog('藏獒')
obj.greet()

示例

在上面代码中,Animal是父类,Dog是子类,我们在Dog类定义了greet方法,为了能同时实现父类的功能,我们又调用了父类的方法。
super的一个最常见用法可以说是在子类中调用父类的初始化方法了。

深入super:

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

首先看一个复杂点的例子,涉及多继承:

class Base(object):
def __init__(self):
print('enter base')
print('leave base') class A(Base):
def __init__(self):
print('enter A')
super(A, self).__init__()
print('leave A') class B(Base):
def __init__(self):
print('enter B')
super(B, self).__init__()
print('leave B') class C(A, B):
def __init__(self):
print('enter C')
super(C, self).__init__()
print('leave C') obj = C()

示例

其中,Base是父类,A、B继承Base,C继承A和B,执行结果如下:

enter C
enter A
enter B
enter base
leave base
leave B
leave A
leave C

如果你认为super代表调用父类的方法,那么你很可能疑惑为什么enterA的下一句不是enterBase而是enterB。原因是,super和父类没有实质性的关联,那么super是怎么运作的呢?
首先看一下MRO表吧:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)

mro表是通过一个C3线性化算法来实现的,遵循三条原则:

  1、子类永远在父类前面

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

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

super原理:

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

其中,cls代表类,inst代表实例,上面的代码做了两件事:
  1、获取inst的mro列表

  2、查找cls在当前mro列表中的index,并返回它的下一个类,即mro[index+1]

当你使用super(cls, inst)时,python会在inst的mro列表中搜索下一个类

现在,再回到上个示例:

首先看C的__init__方法:

super(C, self).__init__()
这里的self是当前实例,即使不创建对象,self也是一个固定的内存地址,这时会打印出enterA,并执行下面一行代码:
super(A, self).__init__()
注意:这里的self也是当前C的实例,mro表跟上面是一样的,搜索A在mro列表中的下一个类,发现是B,于是,跳到了B的__init__,这时会打印出enterB,而不是enter base

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

小结:

事实上,super和父类没有实质性的关联

super(cls,inst)获得的是cls在inst的mro列表中的下一个类。

super深究的更多相关文章

  1. 常用数据结构-线性表及Java 动态数组 深究

    [Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...

  2. WebComponent魔法堂:深究Custom Element 之 标准构建

    前言  通过<WebComponent魔法堂:深究Custom Element 之 面向痛点编程>,我们明白到其实Custom Element并不是什么新东西,我们甚至可以在IE5.5上定 ...

  3. python类中的super,原理如何?MRO是什么东东?

    下面这个URL解释得比较清楚. http://python.jobbole.com/86787/?utm_source=group.jobbole.com&utm_medium=related ...

  4. JavaSE复习日记 : 继承关系和super关键字以及继承关系中方法的覆写

    /* * 类的继承和super关键字 * * 软件开发的三大目的: * 可拓展性; * 可维护性; * 可重用性; * * 这里单说下可重用性这一项: * 为了代码复用,复用方式有: * 函数的调用复 ...

  5. JavaScript学习笔记(散)——继承、构造函数super

    构造函数中的super 今天看<JavaScript设计模式与开发实践>时,在书中看到一段代码出现super语句,第一次看到这个关键字,所以上网查了下它的作用,发现这个关键字是来自java ...

  6. Python super使用

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

  7. Python: 你不知道的 super

    https://segmentfault.com/a/1190000007426467 Python: 你不知道的 super 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我 ...

  8. python: super原理

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

  9. Angular 个人深究(二)【发布与订阅】

    Angular 个人深究(二)[发布与订阅] 1. 再入正题之前,首先说明下[ 发布与订阅模式](也叫观察者模式) 1) 定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个 ...

随机推荐

  1. c#读取html文件内容替换之后再写入

    string sss = File.ReadAllText("E:\\FM\\Mall\\MallSGWeb\\MallSGWeb\\MALL_simple\\File\\11111.htm ...

  2. bonecp回缩功能实现

    起因 bonecp不具备回缩功能,即连接池持有连接之后,不会主动去释放这些连接(即使这些连接始终处于空闲状态),因此在使用一段时间之后,连接池会达到配置的最大值. 这种方式一定程度上造成了资源的浪费. ...

  3. 【转】类找不到总结java.lang.ClassNotFoundException

    (1)org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.microsoft.sqls ...

  4. 中小型研发团队架构实践九:任务调度Job

    一.Job 简介 Job 类似于数据库中的作业,多用于实现定时执行任务.适用场景主要包括定时轮询数据库同步.定时处理数据.定时邮件通知等. 我们的 Job 分为操作系统级别定时任务 WinJob 和 ...

  5. Android开发之旅2:HelloWorld项目的目录结构

    引言 前面Android开发之旅:环境搭建及HelloWorld,我们介绍了如何搭建Android开发环境及简单地建立一个HelloWorld项目,本篇将通过HelloWorld项目来介绍Androi ...

  6. MySQL内连接和外连接

    INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录. LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录. RIGHT JOIN(右连接): 与 LEF ...

  7. gulpjs的使用介绍及技巧

    gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...

  8. 阿里云 CentOS7安装redis4.0.9并开启远程访问

    1 安装redis编译的c环境 yum install gcc-c++ redis是c语言开发的,安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境. 如果没有gcc环境,需要安装gcc ...

  9. php Closure::bind的参数说明

    publicstatic Closure Closure::bind ( Closure $closure , object$newthis [, mixed$newscope = 'static' ...

  10. SESSION机制(转)

    转自:http://www.cnblogs.com/zyf-zhaoyafei/p/4477175.html 一:Session与Cookie Session:在服务器端创建并存放在服务器的内存中的, ...