一、多态
当多个子类继承同一个父类时,在各个子类中都可以重载父类的成员。通过各自的重载,父类的某一成员在不同的子类中就会有不同的“表现”,这种现象就叫“多态”。例如:
class b01: x=0
class cls01(b01):x=11
class cls02(b01):x=22
class cls03(b01):x=33
class cls04(b01):x=44
class cls05(b01):x=55
print(cls01.x, cls02.x, cls03.x, cls04.x, cls05.x) # 11 22 33 44 55
以上例子中基类中定义的变量 x,当用不同的子类中,其值各不相同,这就是典型的“多态”现象。不过,以上例子展示的是最简单的多态形式。在实际的子类重载父类成员的过程上,通常都会引用父类的成员,即,父类已有的功能不再重复实现。
在派生类中引用基类成员可以有两种方法:一是用“基类名.成员名”的方法;二是用“super().成员名”的方法。用“基类名.成员名”的方法虽然简单明了,但潜在一个问题:当基类名发生改变时,子类就必须同时进行修改————逐一地在引用基类成员的地方将旧的基类名修改为新的基类名。而用“super().成员名”的方法就可以有效地避免这个问题,所以,“super().成员名”是最常使用的方法。
因为super()函数是依据 MRO列表来运行的,所以要学习super()函数,就需要先了解 MRO列表。
二、MRO列表
MRO(method resolution order),直译:方法解析顺序,即一个描述类的继承关系的列表。每个类在定义之后,Python 运行程序都会依据其继承关系,遵循以下规则计算出 MRO列表,并存放在类的内部。
1、对于单继承,列表中的顺序为:派生类、基类、基类的基类 ······
2、对于多继承,列表中的顺序为:派生类、(第一个基类的 MRO列表)、(第二个基类的 MRO列表) ······
类的 MRO列表,可以通过 print(类名.mro()) 或 print(类名.mro) 的方法查看。例如:
# 示例一:单继承
class c1:pass
class c2(c1):pass
class c3(c2):pass
class c4(c3):pass
print(c4.mro())
# 显示:
[<class '__main__.c4'>, <class '__main__.c3'>, <class '__main__.c2'>, <class '__main__.c1'>, <class
'object'>]
# 即顺序为: c4 ———— c3 ———— c3 ———— c1
#示例二:多继承
class c111:pass
class c112:pass
class c11(c111,c112):pass
class c12:pass
class c1(c11,c12):pass
class c2:pass
class c31:pass
class c3(c31):pass
class c0(c1,c2,c3):pass
print(c0.mro())
# 显示:
[<class '__main__.c0'>, <class '__main__.c1'>, <class '__main__.c11'>, <class '__main__.c111'>, <cla
ss '__main__.c112'>, <class '__main__.c12'>, <class '__main__.c2'>, <class '__main__.c3'>, <class '_
_main__.c31'>, <class 'object'>]
# 即顺序为:c0 ———— c1 ———— c11 ———— c111 ———— c112 ———— c12 ———— c2 ———— c3 ———— c31
三、super()函数
super(type, obj)
typy ———— 类名
obj ———— 必须是第一个参数 type 的子类或子类的对象
返回值 ———— 查看第二个参数 obj 的 MRO列表,即继承顺序,找到紧跟在 type 对应的类之后一个类,并返回。
第一、因为函数的第一步是要在第二个参数 obj 的 MRO列表上找与第一个参数 type 对应的类,所以,obj 必须是 type 的子类或子类对象,以确保 type 在 obj 的 MRO列表上。
第二、返回值是 MRO列表上紧跟在 type 后面的那个类,这个类可能是 type 的父类,可能是 type 的兄弟类,也可能什么也不是。只有在完全单类继承的情况下,返回值才一定是 type 的父类。如果 type 已经是MRO列表上的最后一个类,也就是在 type 不再有类,则报错。
第三、当两个参数都为空时,即super(),返回当前对象对应的类的第一个基类。
例如:
class c111:x=111
class c112:x=112
class c11(c111,c112):x=11
class c12:x=12
class c1(c11,c12):x=1
class c2:x=2
class c31:x=31
class c3(c31):x=3
class c0(c1,c2,c3):
def fun(self):
print(super(c0,c0).x,end='----')
print(super(c1,c0).x,end='----')
print(super(c11,c0).x,end='----')
print(super(c111,c0).x,end='----')
print(super(c112,c0).x,end='----')
print(super(c12,c0).x,end='----')
print(super(c2,c0).x,end='----')
print(super(c3,c0).x)
def fun2(self):
print(super().x)
print(c0.mro())
# 显示:
[<class '__main__.c0'>, <class '__main__.c1'>, <class '__main__.c11'>, <class '__main__.c111'>, <cla
ss '__main__.c112'>, <class '__main__.c12'>, <class '__main__.c2'>, <class '__main__.c3'>, <class '_
_main__.c31'>, <class 'object'>]
# 即顺序为:c0 ———— c1 ———— c11 ———— c111 ———— c112 ———— c12 ———— c2 ———— c3 ———— c31
c0.fun(0) # 1--11--111--112--12--2--3--31
obj01=c0()
obj01.fun2() # 1
来源:CSDN
作者:Jeff888999
链接:https://blog.csdn.net/Jeff888999/article/details/104070197