super深究
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的工作方式,而不是想当然地认为super调用了父类的方法。
小结:
事实上,super和父类没有实质性的关联
super(cls,inst)获得的是cls在inst的mro列表中的下一个类。
super深究的更多相关文章
- 常用数据结构-线性表及Java 动态数组 深究
[Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...
- WebComponent魔法堂:深究Custom Element 之 标准构建
前言 通过<WebComponent魔法堂:深究Custom Element 之 面向痛点编程>,我们明白到其实Custom Element并不是什么新东西,我们甚至可以在IE5.5上定 ...
- python类中的super,原理如何?MRO是什么东东?
下面这个URL解释得比较清楚. http://python.jobbole.com/86787/?utm_source=group.jobbole.com&utm_medium=related ...
- JavaSE复习日记 : 继承关系和super关键字以及继承关系中方法的覆写
/* * 类的继承和super关键字 * * 软件开发的三大目的: * 可拓展性; * 可维护性; * 可重用性; * * 这里单说下可重用性这一项: * 为了代码复用,复用方式有: * 函数的调用复 ...
- JavaScript学习笔记(散)——继承、构造函数super
构造函数中的super 今天看<JavaScript设计模式与开发实践>时,在书中看到一段代码出现super语句,第一次看到这个关键字,所以上网查了下它的作用,发现这个关键字是来自java ...
- Python super使用
一 基础使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: #!/usr ...
- Python: 你不知道的 super
https://segmentfault.com/a/1190000007426467 Python: 你不知道的 super 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我 ...
- python: super原理
super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: ...
- Angular 个人深究(二)【发布与订阅】
Angular 个人深究(二)[发布与订阅] 1. 再入正题之前,首先说明下[ 发布与订阅模式](也叫观察者模式) 1) 定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个 ...
随机推荐
- SQL中的go、begin、end的用法
go 向 SQL Server 实用工具发出一批 Transact-SQL 语句结束的信号.go是把t-sql语句分批次执行.(一步成功了才会执行下一步,即一步一个go) BEGIN 和 END 语句 ...
- DOM-添加元素、节点
createElement()方法能够根据参数指定的标签名称创建一个新元素,并返回新建元素的引用,用法如下 var element=document.createElement("tagNa ...
- Git 小记
感觉用github管理自己平时的一些代码挺方便的,尤其还有各种统计,作为一个码农,就有一种每日签到.累计签到统计的感觉.用github,学习git自然是不可避免的,原先只是用几个 git clone ...
- Maven项目下启动后Eclipse报错:org.springframework.web.context.ContextLoaderListener
严重: Error configuring application listener of class org.springframework.web.context.ContextLoaderLis ...
- JavaScript document和window属性及方法详解
[document对象] 该对象是window和frames对象的一个属性,是显示于窗口或框架内的一个文档. 属性 alinkColor 活动链接的颜色(ALINK) anchor 一个HTMI锚点 ...
- Oracle数据库函数总结
1.ceil()向上取整,结果为124.select ceil(123.123) from dual;2.floor()向下取整,结果为123.select floor(123.123) from d ...
- 用jquery实现带左右按键的轮播图
成品如下: 简单来说就是点击“右”按钮时,转换到右边的下一幅图片,同时上面的小方块颜色也跟着改变,如果已经是最后一幅图片,再点击“右”,则转换到第一幅图片,是直接向左移找到第一幅图的,明天再做一下无缝 ...
- html active属性
源代码 <div class="col-md-3"> <div class="list-group"> <a href=" ...
- 在生产环境中安全执行更新删除SQL脚本的技巧
今天在生产环境上解决问题,由于广发银行的管理制度是开发公司是不允许确生产环境的,所以我们只能把要更新的语句发给运营中心,由运营中心的投产人员执行,我们则在旁边看着:在他执行的时候发现了一个很有趣的技巧 ...
- WPF 手机验证码 发送按钮倒计时 代码
private async void SendButton_Click(object sender, RoutedEventArgs e) { var button = sender as Butto ...