Python类中super()和__init__()的关系
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’>]