python类中super()和__init__()的区别
最近有同学问我关于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()可以制止反复挪用
#p#分页标题#e#
假如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 [, , , ]