super()与__init__()
一、概述
__init__()一般用来创建对象的实例变量,或一次性操作。super()用于调用父类的方法,可用来解决多重继承问题。
单继承中,super()和__init__()功能类似,主要区别:1)使用super()继承则不用显式引用基类,父类发生变化时,利于维护;2)super()只能用于新式类中,需要继承object对象。
而在多重继承时,会涉及继承顺序,直接用类名调用父类方法会涉及查找顺序、重复调用等问题。super()则是返回继承顺序的下一个类,而不是父类。
_init_ 几点说明:
-
子类没有定义自己的初始化函数,父类的初始化函数会被默认调用;要实例化子类的对象,需要传入父类初始化函数对应的参数
-
如果子类定义了自己的初始化函数,而在子类中没有显式调用父类的初始化函数,则父类的属性不会被初始化
-
如果子类定义了自己的初始化函数,在子类中显示调用父类,子类和父类的属性都会被初始化
一般为了使用扩展父类的行为,最好显式调用父类的__init__方法。
二、super()与__init__()区别
1、单继承中super()和__init__()实现功能类似,super()不用显式引用基类
class Base(object):
def __init__(self, name):
self.name = name
print("Base create")
def func(self):
print("base fun")
class childA(Base):
def __init__(self):
print("childA create")
Base.__init__(self, "A") # 父类名硬编码到子类中
def funA(self):
print("funA")
class childB(Base):
def __init__(self):
print("childB create")
super(childB, self).__init__('B') # super,将子类名和self传递进去
if __name__ == '__main__':
A = childA()
#A.func()
B = childB()
运行结果:
2、super()只能用于新式类
首先说明新式类与经典类的定义:
经典类是默认没有派生自某个基类的,而新式类默认派生自object基类,Python3之后的版本就只承认新式类了。
经典类在类多重继承时,采用从左至右深度优先的匹配方法,可能会存在查询继承树中绕过后面的父类等问题,而新式类采用C3算法进行匹配的。如:
class D():
def foo(self):
print "class D"
class B(D):
pass
class C(D):
def foo(self):
print "class C"
class A(B, C):
pass
f = A()
f.foo()
经典类采用深度优先的匹配方法,输出class D。新式类采用C3算法(区别与广度优化),输出class C。
3、多重继承-super不是父类,而是继承顺序的下一个类
super()返回的不是父类,而是继承顺序的下一个类
class Base(object):
def __init__(self):
print("Base Create")
class childA(Base):
def __init__(self):
print("init A")
# Base.__init__(self)
super(childA, self).__init__()
print("init A end")
class childB(Base):
def __init__(self):
print("init B")
# Base.__init__(self)
super(childB, self).__init__()
print("init B end")
class childC(childA, childB):
pass
运行结果:
super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().__init__(),这样顺序执行下去。执行顺序是A->B->Base。
如果把childA()中的 super(childA, self).__init__() 换成Base._init_(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB。
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("A create")
Base.__init__(self)
print("A create End")
class childB(childA, Base):
def __init__(self):
childA.__init__(self)
Base.__init__(self)
运行结果:
super则可以解决此重复调用的问题:
class Base(object):
def __init__(self):
print("Base create")
class childA(Base):
def __init__(self):
print("A create")
super(childA, self).__init__()
print("A create End")
class childB(childA, Base):
def __init__(self):
super(childB, self).__init__()
运行结果: