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 将字符串转换成字典dict
Mar 24 Python
python中的实例方法、静态方法、类方法、类变量和实例变量浅析
Apr 26 Python
python处理PHP数组文本文件实例
Sep 18 Python
对于Python装饰器使用的一些建议
Jun 03 Python
Python自定义类的数组排序实现代码
Aug 28 Python
Python中str.format()详解
Mar 12 Python
Python3实现发送QQ邮件功能(附件)
Dec 23 Python
浅谈Pandas 排序之后索引的问题
Jun 07 Python
Django框架模型简单介绍与使用分析
Jul 18 Python
keras实现theano和tensorflow训练的模型相互转换
Jun 19 Python
详解pytorch tensor和ndarray转换相关总结
Sep 03 Python
基于Python实现全自动下载抖音视频
Nov 06 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
自己做矿石收音机
2021/03/02 无线电
PHP的ASP防火墙
2006/10/09 PHP
PHP实现抓取HTTPS内容
2014/12/01 PHP
PHP中error_log()函数的使用方法
2015/01/20 PHP
php读取csc文件并输出
2015/05/21 PHP
PHP基于递归实现的约瑟夫环算法示例
2017/08/27 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
2019/08/12 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
用js判断浏览器是否是IE的比较好的办法
2007/05/08 Javascript
javascript实现Email邮件显示与删除功能
2015/11/21 Javascript
JS组件系列之Bootstrap Icon图标选择组件
2016/01/28 Javascript
javascript深拷贝(deepClone)详解
2016/08/24 Javascript
详解JS数据类型的值拷贝函数(深拷贝)
2017/07/13 Javascript
浅谈Angular2 模块懒加载的方法
2017/10/04 Javascript
封装运动框架实战左右与上下滑动的焦点轮播图(实例)
2017/10/17 Javascript
微信小程序开发(三):返回上一级页面并刷新操作示例【页面栈】
2020/06/01 Javascript
Python实现基于权重的随机数2种方法
2015/04/28 Python
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
Numpy数组的保存与读取方法
2018/04/04 Python
Python中一些不为人知的基础技巧总结
2018/05/19 Python
python中使用zip函数出现错误的原因
2018/09/28 Python
python 将对象设置为可迭代的两种实现方法
2019/01/21 Python
Python队列RabbitMQ 使用方法实例记录
2019/08/05 Python
Python通过Manager方式实现多个无关联进程共享数据的实现
2019/11/07 Python
python中resample函数实现重采样和降采样代码
2020/02/25 Python
python获取系统内存占用信息的实例方法
2020/07/17 Python
Scrapy项目实战之爬取某社区用户详情
2020/09/17 Python
Keras保存模型并载入模型继续训练的实现
2021/02/20 Python
StubHub巴西:购买和出售您的门票
2016/07/22 全球购物
某公司的.net工程师面试题笔试题
2013/11/22 面试题
办理信用卡工作证明
2014/01/11 职场文书
《一株紫丁香》教学反思
2014/02/19 职场文书
安全保证书格式
2015/02/28 职场文书
2015年乡镇平安建设工作总结
2015/05/13 职场文书
Redis可视化客户端小结
2021/06/10 Redis
Android开发手册自定义Switch开关按钮控件
2022/06/10 Java/Android