1.MRO
首先介绍mro(method resolution order)
若有代码
class A(object):
pass
class B(A):
pass
class C(B):
pass
print(C.mro())
执行,输出结果为
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
此即为C类的继承关系。我们可以通过类的mro()方法来查看其mro链条,即C->B->A->Object
2.super引入
我们先感性地认识一下super。super是一个类,可看作:针对问题“如何在执行某个类的__init__方法时沿着mro链条继承之前类的__init__方法”提出。
光看这句话也许会糊涂,这里稍微说明一下
若有代码
class A(object):
def __init__(self):
print("A")
pass
class B(A):
def __init__(self):
print("B")
pass
class C(B):
def __init__(self):
print("C")
pass
C()
执行,输出结果为
C
看见没有?C是由A,B一路继承而来,但在初始化时,只会执行自己的初始化方法,却不执行父类的初始化方法,这并不符合继承的有关理念,super可以用来解决该问题。
3.不使用super时
若有代码
class A(object):
def __init__(self):
print("A")
pass
class B(A):
def __init__(self):
print("B")
pass
class C(B):
def __init__(self):
B.__init__(self)
A.__init__(self)
print("C")
pass
C()
执行,有
B
A
C
看见没有?我们直接在C的初始化方法里调用了B和A的初始化方法,也可以达成目的。但这种方法在继承关系更加复杂,以及某些情况下会出现一些问题,且代码不利于维护,因此我们采用super来更加优雅地解决该问题
4.super简介
在pycharm中输入super,指针放到super上,按ctrl+鼠标左键,即可看见super类的有关介绍
"""
super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
def meth(self, arg):
super().meth(arg)
This works for class methods too:
class C(B):
@classmethod
def cmeth(cls, arg):
super().cmeth(arg)
"""
看不懂没关系,下面简要说明:
super(参数一,参数二)会接收2个参数
从功能的角度来看,参数一决定指向的MRO链条的下一个节点,参数二决定MRO链条
从参数的类型来看 ,参数一填入类,参数二根据需要继承的方法可以①填入实例②填入类(分别对应实例方法、类方法),且会把参数二直接传入调用的函数(之后会有代码举例)
简单举个例子:若参数一填入C,参数二填入C。
则参数一决定了下一个节点为B,也就是说将要继承B中的某个方法。
而参数二不是决定MRO链条的吗?由于此处参数二为C,则可看作引入了链条C->B->A->Object。
从功能的角度来说,参数一限定得比较死板,因为它决定了你到底需要引入哪个函数的方法;而参数二相对灵活,因为参数二承担引入链条的作用,只要该引入的链条包含了参数一对应的类即可。(假如C还有一个子类D,则参数二也可以为D,因为此链条依然包含参数一的类,即A)
现在看一下代码举例(
class A(object):
def __init__(self):
print("A")
pass
class B(A):
def __init__(self):
super(B,self).__init__()
print("B")
pass
class C(B):
def __init__(self):
super(C,self).__init__()
print("C")
pass
C()
输出结果为
A
B
C
可以看见,实现了预期目的
稍微提醒一下,这里super所属行的最后,__init__()括号中是没有参数的,因为正如之前所说,super的第二个参数会直接传入之后的调用方法之中
讲解到此结束,这是非常粗糙的理解,因为应用场景稍微变化,传入参数可能就需要有相应调整,读者应该将本教程视为对super的简单理解,需要自己动手才能进一步掌握super的用法
如有错误,欢迎指出,谢谢