转自:https://blog.csdn.net/weixin_41798111/article/details/117623958
super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
钻石继承: 子类继承自两个单独的超类,而两个超类又继承自同一个公共基类。
class MyBaseClass(object):
def __init__(self, value):
self.value = value
class TimesTwo(MyBaseClass):
def __init__(self, value):
MyBaseClass.__init__(self,value)
self.value *= 2
class PlusFive(MyBaseClass):
def __init__(self,value):
MyBaseClass.__init__(self,value)
self.value += 5
class ThisWay(PlusFive,TimesTwo):
def __init__(self, value):
PlusFive.__init__(self, value)# value = 13
TimesTwo.__init__(self, value) #value = 16
foo = ThisWay(8)
print(foo.value)
输出结果是16。
因为执行顺序为PlusFive的构造函数后调用基类MyBaseClass的构造函数,value=8,PLusFive构造函数value=13,执行TimeTwo的构造函数会再次调用基类MyBaseClass的构造函数value=8,再TimeTwo构造函数value=16。
显然我们期待的是 (8+5)*2 ,原因就是构造方法中的__init__无法继承, 需要在构造函数中绑定父类中的__init__,这会导致基类的构造函数运行多次导致,为了解决这个问题,用super初始化超类,避免这种问题产生。
class MyBaseClass(object):
def __init__(self, value):
self.value = value
class TimesTwo(MyBaseClass):
def __init__(self, value):
super(TimesTwo, self).__init__(value)
self.value *= 2
class PlusFive(MyBaseClass):
def __init__(self,value):
super(PlusFive, self).__init__(value)
self.value += 5
class ThisWay(TimesTwo, PlusFive):
def __init__(self, value):
super(ThisWay, self).__init__(value)
foo = ThisWay(8)
print(foo.value)
from pprint import pprint
pprint(ThisWay.mro())
结果输出:
26
[<class '__main__.ThisWay'>,
<class '__main__.TimesTwo'>,
<class '__main__.PlusFive'>,
<class '__main__.MyBaseClass'>,
<class 'object'>]
如果改变ThisWay中超类定义顺序:
class ThisWay(PlusFive, TimesTwo):
def __init__(self, value):
super(ThisWay, self).__init__(value)
输出结果:
21
[<class '__main__.ThisWay'>,
<class '__main__.PlusFive'>,
<class '__main__.TimesTwo'>,
<class '__main__.MyBaseClass'>,
<class 'object'>]
结果和ThisWay定义超类顺序有关。
第一种情况先定义TimesTwo,后定义PlusFive,根据MRO可以看到初始化顺序,倒过来即是执行顺序,(8+5)*2=26。
第二种情况同理,8*2 +5 = 21
以上对super是Python2 的定义形式,比较复杂。需要指定当前类和指定相关的方法名称,这里是__init__(),以及方法的参数。
下面是Python3 定义形式:
class MyBaseClass(object):
def __init__(self, value):
self.value = value
class TimesTwo(MyBaseClass):
def __init__(self, value):
super().__init__(value)
self.value *= 2
class PlusFive(MyBaseClass):
def __init__(self,value):
super().__init__(value)
self.value += 5
class ThisWay(PlusFive, TimesTwo):
def __init__(self, value):
super().__init__(value)
foo = ThisWay(8)
print(foo.value)
代码比较简洁。