多继承
一个子类继承多个父类,就是多继承,并且拥有所有父类的属性和方法
例如:孩子会继承父亲和母亲的特征
如果子类和父类中有相同的方法,就会调用子类中的方法
如果不同的父类中存在有相同的方法名称,子类对象调用的时候会调用哪个父类中的方法呢?
python 会根据MRO(method resolution order) 方法解析顺序列表进行查找。
class Dog:
def eat(self):
print("吃骨头")
class God:
def eat(self):
print("吃上帝")
class Thing(God,Dog):
pass
thing = Thing()
thing.eat()
print(Thing.__mro__)
# 吃上帝
# (<class '__main__.Thing'>, <class '__main__.God'>, <class '__main__.Dog'>, <class 'object'>)
MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据他们在列表中的顺序进行检查
3.如果对下一个类中有两个合法的选择,选择第一个父类
class A:
def func(self):
print("----A----")
class B(A):
def func(self):
print("----B----")
class C(A):
def func(self):
print("----B-----")
class D(B,C):
pass
d = D()
d.func()
print(D.__mro__)
print(D.mro())
# ----B----
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
多继承中super本质不是直接查找父类,而是根据调用节点的广度优先顺序执行的
练习:创建 A、B、C、D 类,D 类继承 B,C 类,B 类继承 A 类,C 类继承 A 类。
在每个方法中都调用 super().func()方法,查看执行顺序。
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() # 继承顺序 D-->B-->C-->A
#结果:A,C,B,D
print(D.__mro__)
print(D.mro())
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
如图,B 继承 A, C 继承 A, D 继承 B 和 C。
深度优先遍历是从 D 开始往上搜索到 B,若 B 没有数据,则继续往上搜索到 A;
广度优先遍历是从 D 开始往上搜索到 B,若 B 没有数据,则搜索和 B 同级的 C 里的数据,若同级的 C 里还是没有数据,再继续往上搜索到 A 。
Tips:py2 经典类是按深度优先来继承的,新式类是按广度优先来继承的。
py3 经典类和新式类都是统一按广度优先来继承的
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):
def func(self):
super(D, self).func()
print("----D-----")
class E(C):
def func(self):
super(E, self).func()
print("----E-----")
class F(D, E):
def func(self):
super(F, self).func()
print("----F-----")
f = F()
f.func() # 继承顺序 D-->B-->C-->A
# ----A----
# ----C-----
# ----E-----
# ----B----
# ----D-----
# ----F-----
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(C):
def func(self):
super(D, self).func()
print("----D-----")
class E(B):
def func(self):
super(E, self).func()
print("----E-----")
class G(B):
def func(self):
super(G, self).func()
print("----G-----")
class H(A):
def func(self):
super(H, self).func()
print("----H-----")
class F(D, E,G,H):
def func(self):
super(F, self).func()
print("----F-----")
f = F()
f.func()
# ----A----
# ----H-----
# ----B----
# ----G-----
# ----E-----
# ----C-----
# ----D-----
# ----F-----
class A1: pass
class A2: pass
class A3: pass
class B1(A1,A2): pass
class B2(A2): pass
class B3(A2,A3): pass
class C1(B1): pass
class C2(B1,B2): pass
class C3(B2,B3): pass
class D(C1, C2, C3): pass
print("从D开始查找:")
for s in D.__mro__:
print(s)
# 从D开始查找:
# <class '__main__.D'>
# <class '__main__.C1'>
# <class '__main__.C2'>
# <class '__main__.B1'>
# <class '__main__.A1'>
# <class '__main__.C3'>
# <class '__main__.B2'>
# <class '__main__.B3'>
# <class '__main__.A2'>
# <class '__main__.A3'># <class 'object'>
多态
面向对象三大特性: 封装、继承、多态
1.封装:屏蔽提供细节,但提供调用方式,将功能封装成一个整体,提供简单的调用方式
2.继承:可以拥有另一个类的方法和属性
3.多态:让某个类呈现多种形态
实现多态的三个条件: 1.必须存在继承关系 2.重写目标方法 3.使用子类对象调用父类方法
定义人类,可以跳舞,可以玩,在玩的过程跳舞
实现多态,老年人跳广场舞
class Person:
def dance(self):
print('跳舞')
def play(self):
self.dance() #old.dance()
class Oldman(Person):
def dance(self):
print("跳广场舞")
old = Oldman()
old.play()
per = Person()
per.play()