Python中的super()
python中对象方法的定义很怪异,第一个参数一般都命名为self(相当于其它语言的this),用于传递对象本身,有时候还会有一个参数cls(相当于类名,当直接调用类方法的时候使用)。
python2中super()的用法:
super(class, self).__init__()
python3中super()的用法:
super().__init__()
在类的继承里面super()非常常用, 它解决了子类调用父类方法的一些问题, 父类多次被调用时只执行一次。
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
当使用 super(cls, inst) 时,Python 会在 inst 的类的 MRO 列表上搜索 cls 的下一个类。而查看inst类的MRO列表的方法就是:类.mro() 或 类.__mro__ 或 inst.__class__.mro()
例如:当C是一个类的时候,获得一个类的MRO的方法是:C.mro() 或 C.__mro__ 或 C().__class__.mro()

执行过程:
当生成D的inst对象时,先执行Enter D,此时D类的MRO列表为:[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
当执行super(D,self)时,就是在self对象的类的MRO列表中查找D的下一个父类。此时,这个self就是D类的实例对象inst。而D类中的MRO列表中D的下一个父类是B。
例如:
1.super为单继承时:
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
b = B()
b.add(2)
print(b.n)
结果是什么呢?

为什么是8?
因为在执行b.add(2)的时候,执行A中的add()函数,而此时在A.add()函数中self是b这个实例,因此self.n是3。
所以执行3 + 2 = 5
然后执行super的下一句5 + 3 = 8。
2.super为多继承时
# super的多继承
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m)
self.n += 4
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
print('self is {0} @D.add'.format(self))
super().add(m)
self.n += 5
d = D()
d.add(2)
print(d.n)
这个结果是什么呢?
我认为是5 + B.add + C.add + A.add + 5 = 5 + 3 + 4 + 2 + 5 = 19
看下输出的结果:

执行过程是什么样的呢?详细的代码分析如下:
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m # 第4步执行,A.add(2),此时self = b,n = 5,即n = 5 + 2 = 7
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m) # 第2步执行,相当于super(B, d),在d的MRO[D, B, C, A, Object]中B的下一个C.add(2),此时self = b,n = 5
self.n += 3 # 第6步执行,n = 11 + 3 = 14
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m) # 第3步执行,相当于super(C, d),在d的MRO[D, B, C, A, Object]中C的下一个A.add(2),此时self = b, n = 5
self.n += 4 # 第5步执行,n = 7 + 4 = 11
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
print('self is {0} @D.add'.format(self))
super().add(m) # 第1步执行相当于super(D, d)此时会返回在d的MRO[D, B, C, A, Object]中D的下一个类B,执行B.add(2)
self.n += 5 # 第7步执行,n = 14 + 5 = 19
d = D()
print(d.__class__.mro()) # d的MRO[D, B, C, A, object]
d.add(2)
print(d.n)
当我们调用 super() 时,其实质是实例化了一个 super 类。在大多数情况下,super 包含了两个非常重要的信息: 一个 MRO 以及 MRO 中的一个类。
当以方式 super(a_type, obj) 调用 super 时,MRO指的是 type(obj) 的 MRO, 而MRO中的那个类就是a_type, 同时 isinstance(obj, a_type) == True 。
当以方式 super(type1, type2) 调用 super 时,MRO 指的是 type2 的 MRO, 而MRO中的那个类就是type1 ,同时 issubclass(type2, type1) == True 。
那么,super() 实际上做了啥呢?简单来说就是:提供一个 MRO 以及一个 MRO 中的类 C , super() 将返回一个从 MRO 中 C 之后的类中查找方法的对象。
也就是说,查找方式不是像常规方法一样从所有的 MRO 类中查找。
举个例子, 有个 MRO 为:[A, B, C, D, E, object],用下面的调用方式:super(C, A).add()
此时,super 只会从 C 之后查找,即:只会在 D 或 E 或 object 中查找 add 方法。
浙公网安备 33010602011771号