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实现的简单FTP上传下载文件实例
Jun 30 Python
老生常谈python之鸭子类和多态
Jun 13 Python
Python实现霍夫圆和椭圆变换代码详解
Jan 12 Python
Python使用functools实现注解同步方法
Feb 06 Python
python web.py开发httpserver解决跨域问题实例解析
Feb 12 Python
django 开发忘记密码通过邮箱找回功能示例
Apr 17 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
May 16 Python
python与字符编码问题
May 24 Python
python3 深浅copy对比详解
Aug 12 Python
Python从列表推导到zip()函数的5种技巧总结
Oct 23 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
Jan 02 Python
python实现凯撒密码、凯撒加解密算法
Jun 11 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实现将任意进制数转换成10进制的方法
2015/04/17 PHP
PHP+iframe图片上传实现即时刷新效果
2016/11/18 PHP
mac os快速切换多个PHP版本的方法
2017/03/07 PHP
PHP+redis实现的限制抢购防止商品超发功能详解
2019/09/19 PHP
TFDN图片播放器 不错自动播放
2006/10/03 Javascript
HTML颜色选择器实现代码
2010/11/23 Javascript
让浏览器非阻塞加载javascript的几种方法小结
2011/04/25 Javascript
改善用户体验的五款jQuery插件分享
2011/05/22 Javascript
33个优秀的jQuery 教程分享(幻灯片、动画菜单)
2011/07/08 Javascript
javascript 上下banner替换具体实现
2013/11/14 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
js解析json读取List中的实体对象示例
2014/03/11 Javascript
jquery mobile的触控点击事件会多次触发问题的解决方法
2014/05/08 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
使用jQuery实现鼠标点击左右按钮滑动切换
2017/08/04 jQuery
vue 点击按钮增加一行的方法
2018/09/07 Javascript
详解Node.js amqplib 连接 Rabbit MQ最佳实践
2019/01/24 Javascript
Nodejs对postgresql基本操作的封装方法
2019/02/20 NodeJs
解决layui页面按钮点击无反应,也不报错的问题
2019/09/29 Javascript
javascript 原型与原型链的理解及实例分析
2019/11/23 Javascript
在Python的web框架中中编写日志列表的教程
2015/04/30 Python
python中enumerate函数遍历元素用法分析
2016/03/11 Python
Python实现文件信息进行合并实例代码
2018/01/17 Python
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
django框架使用orm实现批量更新数据的方法
2019/06/21 Python
让Django的BooleanField支持字符串形式的输入方式
2020/05/20 Python
详解CSS3原生支持div铺满浏览器的方法
2018/08/30 HTML / CSS
比较一下entity bean和session bean
2013/12/27 面试题
数控专业应届生求职信
2013/11/27 职场文书
情人节寄语大全
2014/04/11 职场文书
机关党员公开承诺书
2014/08/30 职场文书
2014年无财产无子女离婚协议书范本
2014/10/09 职场文书
三峡人家导游词
2015/01/31 职场文书
明星邀请函
2015/02/02 职场文书
省级三好学生主要事迹材料
2015/11/03 职场文书
总结Python使用过程中的bug
2021/06/18 Python