python类中super()和__init__()的区别
- 编程
- 2023-02-10
最近有同学问我关于Python类中的super()和__init__()共同点和不同点的问题, 我今天把它们两个的异同点总结了一下,希望可以帮助遇到同样困惑的同学。
单继承时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 (, , , , )
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 (, , , , )
从super()方法可以看出,super()的第一个参数可以是继承链中任意一个类的名字,
如果是本身就会依次继承下一个类;
如果是继承链里之前的类便会无限递归下去;
如果是继承链里之后的类便会忽略继承链汇总本身和传入类之间的类;
比如将childA()中的super改为:super(childC, self).__init__(),程序就会无限递归下去。 如:
File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, in __init__ super(childC, self).__init__() File "test.py", line 12, 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 [, , , ]
- 初学者学习python2还是python3?
- python获取本机IP、mac地址、计算机名
- 详解python2 和 python3的区别
- python基础之删除文件及删除目录的方法
- 用python求第1000个质数的值
- python常用函数年初大总结
- Python3 - 时间处理与定时任务
- Python开发的CMS系统,Silva CMS 3 发布
- python基础之使用os.system来执行系统命令
- 判断python字典中key是否存在的两种方法
- 初学者学习python2还是python3?
- python基础之删除文件及删除目录的方法
- python获取本机IP、mac地址、计算机名
- python获取系统时间(时间函数详解)
- 详解python2 和 python3的区别
- 用python求第1000个质数的值
- Python3 - 时间处理与定时任务
- 命令行看糗百
- Python算法之---冒泡,选择,插入排序算法
- python 中求和函数 sum详解
- range方法在Python2和Python3中的不同
- python3 数组(列表)初始化
- 记一次crontab中date命令错用导致的问题
- MySQL用LIKE特殊字符搜索
- CentOS 7 下修改主机名
- Python3正则表达式之:(?(id/name)y...
- TIOBE编程语言排行榜2019年 Python稳居前三
- 解压命令unzip常用方法汇总
- 解析redis备份文件rdb的两种方法及对比
- 百度视觉语义化平台2.0:交互升级和...
- 5G时代的视觉语义化技术:软硬结合...
- 百度AutoDL重磅升级至3.0:设计、迁...