Python super() 函数
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,通过使用 super
来实现
语法:super(type[, object-or-type])
- type -- 类。
- object-or-type -- 类,一般是 self
- 无返回值
Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
Python3.x 实例:
class A:
pass
class B(A):
def add(self, x):
super().add(x)
Python2.x 实例:
class A(object): # Python2.x 记得继承 object
pass
class B(A):
def add(self, x):
super(B, self).add(x)
实例
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name class Dog(Animal):
def greet(self):
super(Dog, self).greet() # Python3 可使用 super().greet()
print 'WangWang...'
在上面,Animal 是父类,Dog 是子类,我们在 Dog 类重定义了 greet
方法,为了能同时实现父类的功能,我们又调用了父类的方法,看下面的使用:
>>> dog = Dog('dog')
>>> dog.greet()
Hello, I am dog.
WangWang..
深入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"
其中,Base 是父类,A, B 继承自 Base, C 继承自 A, B,它们的继承关系如下:
Base
/ \
A B
\ /
C
现在,让我们看一下使用:
>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C
如果你认为 super
代表『调用父类的方法』,那你很可能会疑惑为什么 enter A 的下一句不是 enter Base 而是 enter B。原因是,super
和父类没有实质性的关联,现在让我们搞清 super
是怎么运作的。
MRO 列表
事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表:
>>> C.mro() # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]
那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:
- 子类永远在父类前面
- 如果有多个父类,会根据它们在列表中的顺序被检查
- 如果对下一个类存在两个合法的选择,选择第一个父类
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 的下一个类。
现在,让我们回到前面的例子。
首先看类 C 的 __init__
方法:
super(C, self).__init__()
这里的 self 是当前 C 的实例,self.__class__.mro() 结果是:
[__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。
整个过程还是比较清晰的,关键是要理解 super 的工作方式,而不是想当然地认为 super 调用了父类的方法。
Python super() 函数的更多相关文章
- Python super() 函数的概念和例子
概念: super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重 ...
- python super()函数详解
引言: 在类的多继承使用场景中,重写父类的方法时,可能会考虑到需要重新调用父类的方法,所以super()函数就是比较使用也很必要的解决方法: 文章来源: http://www.cnblogs.com/ ...
- python super()函数:调用父类的构造方法
python子类会继承父类所有的类属性和类方法.严格来说,类的构造方法其实就是实例方法,因此,父类的构造方法,子类同样会继承. 我们知道,python是一门支持多继承的面向对象编程语言,如果子类继承的 ...
- Python setattr() 函数 ,Python super() 函数: Python 内置函数 Python 内置函数
描述 setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在. 语法 setattr 语法: setattr(object, name, value) 参数 object -- ...
- Python中super函数的用法
之前看python文档的时候发现许多单继承类也用了super()来申明父类,那么这样做有何意义? 从python官网文档对于super的介绍来看,其作用为返回一个代理对象作为代表调用父类或亲类方法.( ...
- python之super()函数
python之super()函数 python的构造器奇特, 使用魔方. 构造器内对基类对象的初始化同样也很奇特, 奇特到没有半点优雅! 在构造器中使用super(class, instance)返回 ...
- 由Python的super()函数想到的
python-super *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...
- Python面试题之Super函数
这是个高大上的函数,在python装13手册里面介绍过多使用可显得自己是高手 23333. 但其实他还是很重要的. 简单说, super函数是调用下一个父类(超类)并返回该父类实例的方法. 这里的下一 ...
- python 面向对象十一 super函数
python 面向对象十一 super函数 super函数用来解决钻石继承. 一.python的继承以及调用父类成员 父类: class Base(object): def __init__(se ...
随机推荐
- 20135220谈愈敏Blog5_系统调用(下)
系统调用(下) 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 给Me ...
- 冲刺Two之站立会议4
在完成了对主界面的设计之后,我们对自己的聊天室界面进行了优化,添加了一些标签和图片按钮等组件让界面更加美观一些.然后还查询了一些关于改进视频和音频质量的资料,准备开展相关工作.
- 做业5.2 TDD
package runok;import java.util.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt ...
- Daily Scrum 11.1
今天放假一天,明天又是新的一周,预计开始Alpha版本所有功能的整合和优化,争取在两天内完成各种功能的整合. Member Task on 11.1 Task on 11.2 仇栋民 放假一天 开始T ...
- python获取命令行参数的方法(汇总)
介绍python获取命令行参数的方法:getopt模和argparse模块. python版本:2.7 一.getopt模块 主要用到了模块中的函数: options, args = getopt.g ...
- django学习--1
1 安装 安装anacanda后 conda install django 2 新建项目 django-admin.py startproject HelloWorld 创建完成后我们可以查看下项目的 ...
- 正则js
匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配HTML标记的正则表达式:/&l ...
- [转帖]SQLSERVER 使用触发器实现 禁用sa用户 在非本机登录
原贴地址: https://blog.csdn.net/reblue520/article/details/51580102 具体的方法为: 创建一个触发器 CREATE TRIGGER forbid ...
- PHP阿里云云解析签名, 通过API 绑定域名到动态 ip
<?php date_default_timezone_set("GMT"); //绑定 ip 到域名 Ali::Obj()->UpdateDomainRecord() ...
- vue 请求后台数据 (copy)
https://www.cnblogs.com/calledspeed001/p/7094494.html var that=this get请求 that.$http.get("1.txt ...