python类中super()和__init__()的区别


Posted in Python onOctober 18, 2016

单继承时super()和__init__()实现的功能是类似的

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'creat A ',
Base.__init__(self)
class childB(Base):
def __init__(self):
print 'creat B ',
super(childB, self).__init__()
base = Base()
a = childA()
b = childB()

输出结果:

Base create
creat A Base create
creat B Base create

区别是使用super()继承时不用显式引用基类。

super()只能用于新式类中

把基类改为旧式类,即不继承任何基类

class Base():
def __init__(self):
print 'Base create'

执行时,在初始化b时就会报错:

super(childB, self).__init__()
TypeError: must be type, not classobj

super不是父类,而是继承顺序的下一个类

在多重继承时会涉及继承顺序,super()相当于返回继承顺序的下一个类,而不是父类,类似于这样的功能:

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

mro()用来获得类的继承顺序。

例如:

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'enter A '
# Base.__init__(self)
super(childA, self).__init__()
print 'leave A'
class childB(Base):
def __init__(self):
print 'enter B '
# Base.__init__(self)
super(childB, self).__init__()
print 'leave B'
class childC(childA, childB):
pass
c = childC()
print c.__class__.__mro__

输出结果如下:

enter A 
enter B 
Base create
leave B
leave A
(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

supder和父类没有关联,因此执行顺序是A —> B—>—>Base

执行过程相当于:初始化childC()时,先会去调用childA的构造方法中的 super(childA, self).__init__(), super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().__init()__,这样顺序执行下去。

在多重继承里,如果把childA()中的 super(childA, self).__init__() 换成Base.__init__(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB:

enter A 
Base create
leave A
(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

从super()方法可以看出,super()的第一个参数可以是继承链中任意一个类的名字,

如果是本身就会依次继承下一个类;

如果是继承链里之前的类便会无限递归下去;

如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;

比如将childA()中的super改为:super(childC, self).init(),程序就会无限递归下去。

如:

File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
RuntimeError: maximum recursion depth exceeded while calling a Python object

super()可以避免重复调用

如果childA基础Base, childB继承childA和Base,如果childB需要调用Base的__init__()方法时,就会导致__init__()被执行两次:

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'enter A '
Base.__init__(self)
print 'leave A'
class childB(childA, Base):
def __init__(self):
childA.__init__(self)
Base.__init__(self)
b = childB()

Base的__init__()方法被执行了两次

enter A 
Base create
leave A
Base create

使用super()是可避免重复调用

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'enter A '
super(childA, self).__init__()
print 'leave A'
class childB(childA, Base):
def __init__(self):
super(childB, self).__init__()
b = childB()
print b.__class__.mro()
enter A 
Base create
leave A
[<class '__main__.childB'>, <class '__main__.childA'>, <class '__main__.Base'>, <type 'object'>]

以上所述是小编给大家介绍的python类中super()和__init__()的区别,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
python中尾递归用法实例详解
Apr 28 Python
Python的Twisted框架中使用Deferred对象来管理回调函数
May 25 Python
关于Python面向对象编程的知识点总结
Feb 14 Python
Python中工作日类库Busines Holiday的介绍与使用
Jul 06 Python
Python3利用Dlib19.7实现摄像头人脸识别的方法
May 11 Python
python pexpect ssh 远程登录服务器的方法
Feb 14 Python
pandas DataFrame索引行列的实现
Jun 04 Python
python集合是否可变总结
Jun 20 Python
对pyqt5之menu和action的使用详解
Jun 20 Python
详解Django CAS 解决方案
Oct 30 Python
Pyqt5自适应布局实例
Dec 13 Python
Python 利用argparse模块实现脚本命令行参数解析
Dec 28 Python
Python 序列的方法总结
Oct 18 #Python
python 异常处理总结
Oct 18 #Python
python 队列详解及实例代码
Oct 18 #Python
django model去掉unique_together报错的解决方案
Oct 18 #Python
django批量导入xml数据
Oct 16 #Python
python中os模块详解
Oct 14 #Python
python append、extend与insert的区别
Oct 13 #Python
You might like
虚拟主机中对PHP的特殊设置
2006/10/09 PHP
WML,Apache,和 PHP 的介绍
2006/10/09 PHP
php daodb插入、更新与删除数据
2009/03/19 PHP
PHP验证码生成原理和实现
2016/01/24 PHP
PHP+JS三级菜单联动菜单实现方法
2016/02/24 PHP
PHP版微信小店接口开发实例
2016/11/12 PHP
浅析PHP7 的垃圾回收机制
2019/09/06 PHP
IE innerHTML,outerHTML所引起的问题
2009/06/04 Javascript
js ondocumentready onmouseover onclick onmouseout 样式
2010/07/22 Javascript
JS解析XML文件和XML字符串详解
2015/04/17 Javascript
整理AngularJS中的一些常用指令
2015/06/16 Javascript
js表单提交和submit提交的区别实例分析
2015/12/10 Javascript
angularjs在ng-repeat中使用ng-model遇到的问题
2016/01/21 Javascript
三个js循环的关键字示例(for与while)
2016/02/16 Javascript
浅谈JQuery+ajax+jsonp 跨域访问
2016/06/25 Javascript
微信JS-SDK自定义分享功能实例详解【分享给朋友/分享到朋友圈】
2016/11/25 Javascript
jQuery操作attr、prop、val()/text()/html()、class属性
2019/05/23 jQuery
node.js实现简单的压缩/解压缩功能示例
2019/11/05 Javascript
vuex actions异步修改状态的实例详解
2019/11/06 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
微信小程序实现文件预览
2020/10/22 Javascript
[02:45]DOTA2英雄基础教程 伐木机
2013/12/23 DOTA
[41:54]2018DOTA2亚洲邀请赛 4.1 小组赛A组加赛 TNC vs Liquid
2018/04/03 DOTA
详解Python的Django框架中的模版相关知识
2015/07/15 Python
详解python如何调用C/C++底层库与互相传值
2016/08/10 Python
python+pyqt实现右下角弹出框
2017/10/26 Python
numpy matrix和array的乘和加实例
2018/06/28 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
实习自我鉴定模板
2013/09/28 职场文书
小学岗位竞聘方案
2014/01/22 职场文书
2014年党务公开实施方案
2014/02/27 职场文书
对公司合理化的建议书
2014/03/12 职场文书
岗位廉洁从政承诺书
2014/03/27 职场文书
银行求职信怎么写
2019/06/20 职场文书
导游词之鲁迅祖居
2019/10/17 职场文书