文档章节

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

j_hao104
 j_hao104
发布于 2016/05/27 10:06
字数 981
阅读 2.2K
收藏 14

 

 

1、单继承时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()继承时不用显式引用基类。

2、super()只能用于新式类中

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

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

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

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

3、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

4、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'>]

转载请注明来源:开源中国 http://my.oschina.net/jhao104/blog/682322

© 著作权归作者所有

j_hao104

j_hao104

粉丝 218
博文 71
码字总数 111997
作品 2
成都
程序员
私信 提问
加载中

评论(0)

python2和python3的继承方式的不同,广度优先和深度有限

脚踏黄土,头顶清风,不道苦楚,莫问前程!!! --- 参考文章三篇 简书第一篇 ,简书第二篇,博客园的文章,这篇博客园文章讲的很好 通过继承创建的新类称为“子类”或“派生类”,被继承的类...

鹏灬
2018/09/12
126
0
王老板Python面试(10):17道python笔试面试真题

1、一行代码实现1--100之和 利用sum()函数求和 2、如何在一个函数内部修改全局变量 利用global 修改全局变量 3、列出5个python标准库 os:提供了不少与操作系统相关联的函数 sys: 通常用于命...

程序员八阿哥
2018/05/22
0
0
Python 里的 super() 函数和 object.__new__ ()、.__del__() 方法

object.new() 自定义 new() 方法一般并不常用,而且容易与 init() 相混淆。实际上这两个方法也确实相似,比如他们都是在创建类的实例时会被默认调用的方法,而且创建实例时传入的参数也都会传...

lionets
2014/01/17
5K
0
理解Python中super()

文章作者:Tyan 博客:noahsnail.com | CSDN | 简书 1. 单继承 在单继承时,与是一样的。super()避免了基类的显式调用。代码如下: super().init() Base.init() 2. 多继承 与父类没有实质性的...

SnailTyan
2019/03/19
0
0
Python提高笔记整理(二)

1.多继承以及MRO顺序 多继承指的是子类继承多个父类,可以通过三种方式访问父类的方法: 父类名.父类方法(self):这种方式容易造成父类方法被调用多次的问题,而且一旦父类名称发生变化,子类...

我是小谷粒
2018/07/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

郑州开正规费发票

郑州开正规费发票【132 * 50 52 * 90 89】罗生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridg...

zhangyongli
28分钟前
91
0
OSChina 周四乱弹 —— 失业后的阳光太刺眼了

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @大又 :分享Jack Stauber的单曲《Fighter》 《Fighter》- Jack Stauber 手机党少年们想听歌,请使劲儿戳(这里) @theLovelyBugfly :笑死我...

小小编辑
今天
88
0
手把手教你搭建 ELK 实时日志分析平台

本篇文章主要是手把手教你搭建 ELK 实时日志分析平台,那么,ELK 到底是什么呢? ELK 是三个开源项目的首字母缩写,这三个项目分别是:Elasticsearch、Logstash 和 Kibana。 Elasticsearch ...

武培轩
今天
86
0
直播报名 | Service Mesh技术实践分享

近年来,云原生(Cloud Native)逐渐成为一个技术领域内的流行语,热度居高不下。企业正在加速拥抱云原生架构,以此缩短产品发布周期、敏捷响应市场需求,继而从云计算服务中提炼新的价值和技...

百度开发者中心
今天
97
0
Qt 实现QTableView单元格多按钮效果

实现效果预览: 思路: 使用Qt的委托类独自渲染表格的某一列,如上图字段2的那一列。该一个单元格放入多个按钮,重写 QStyledItemDelegate 委托类 paint 方法即可实现上图效果。 代码: 委托...

剑是SR剑
今天
99
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部