1.多继承的概念与几点说明
1.多继承就是一个子类可以同时继承多个父类;
2.有些语言是不支持多继承的,例如 java;
3.多继承的继承顺序:
新式类的多继承采用广度优先原则;经典类的多继承采用深度优先原则;
python3中的类都是经典类,因此,python3 中的多继承都是广度优先;
4.mro() 方法 用于输出多继承时的继承顺序,只适用于新式类(super只适用于python3);
使用方法:类名.mro() 返回此类的父类继承顺序。
2.几种典型的多继承问题
1.若一个子类同时继承多个父类,则其继承顺序由左向右继承
class A:
pass
# def func(self): print('A')
class B:
pass
# def func(self): print('B')
class C:
def func(self): print('C')
class D(A,B,C): # D 继承父类A,B,C
pass
# def func(self): print('D')
d = D()
d.func()
print(D.mro())
可以看到继承顺序:
继承顺序图示:
箭头指向此类的父类,数字是多继承时的寻找顺序,并忽略基类 object 的继承
2.钻石继承:
class A:
# pass
def func(self): print('A')
class B(A):
pass
# def func(self): print('B')
class C(A):
def func(self): print('C')
class D(B,C): # D 继承父类A,B,C
pass
# def func(self): print('D')
d = D()
d.func()
继承顺序图示:
3.漏斗形继承关系
class A:
# pass
def func(self): print('A')
class B(A):
pass
# def func(self): print('B')
class E:
def func(self): print('E')
class C(E):
def func(self): print('C')
class D(B,C): # D 继承父类A,B,C
pass
# def func(self): print('D')
d = D()
d.func()
继承顺序图示:
4.乌龟继承
class F:
def func(self): print('F')
class A(F):
pass
# def func(self): print('A')
class B(A):
pass
# def func(self): print('B')
class E(F):
pass
# def func(self): print('E')
class C(E):
pass
# def func(self): print('C')
class D(B,C): # D 继承父类A,B,C
pass
# def func(self): print('D')
d = D()
d.func()
继承顺序图示:
super 函数的本质:
其实super不是针对调用父类而设计的,它的本质是在一个由多个类组成的有序集合中搜寻一个特定的类,即类的mro,并找到这个类中的特定函数,将一个实例绑定到这个函数上,生成一个绑定方法(bound method),并返回这个bound method. 例如如下代码:
class A:
def func(self):
print('A')
class B(A):
def func(self):
super(B, self).func()
print('B')
class C(A):
def func(self):
super(C, self).func()
print('C')
class D(B,C):
def func(self):
super(D, self).func()
print('D')
d = D()
d.func()
输出结果如下:
我们使用 mro 打印出继承顺序:
这个列表的意义是D的实例d在调用一个函数时,首先在B类中找这个函数,如果B中调用了super,则需要从B的下一个类(即C)中找函数,如果在C中又调用了super,则从C的下一个类(即A)中找函数;
因此,上述代码实际上在B中遇到super时就到了C中寻找func()函数,当在C中未找到后去A中寻找func(),在A中找到了func后(打印出 ‘A‘),返回调用点C执行下一条语句,打印出 ‘C’,再返回调用点B执行下一条语句,打印出’B‘,在返回到调用点 ’D‘,打印出 ’D‘, 因此,打印的顺序是 A-C-B-D