一. 什么是继承
继承是以一种新建类的方式,新建的类称之为子类,派生类,被继承的类称为父类,基类,超类。
继承的特性:子类继承父类的属性。
强调:继承是类与类之间的关系。
补充:派生,子类新建的属性,无论是函数属性还是数据属性,都已自己的为准。如果子类的属性与父类的相同,也是以子类自己的为准。
二.为何用继承
好处:减少类与类之间代码的冗余。
在python中,一个子类可以继承多个父类
三.新式类与经典类
在python2中,没有继承object类的类称之为经典类
在python3,继承了object类的类称之为新式类
注意:在python3中只有新式类,类后面没写继承的父类的默认继承了object类。而在python2中必须要在类后面写(object)的才是新式类,所以有时在python3中也会在类后面写上object,是为了兼容python2。
四.属性查找
先找对象自己--->对象所在的类--->父类--->父类...
这里又要分单继承,多继承,菱形继承的情况
单继承:属性查找一层一层网上找,直到找到,或者未找到报错。
多继承:从子类名称后面括号内的父类中,从左往右依次查找每一条父类的分支,第一条父类分支全部查找结束还没找到的情况下,再找下一条父类的分支,直到找到为止(形象的说就是一条路走到黑)。
class A:
x = 'B'
class B:
x = 'B'
class C(A):
x = 'C'
class D(B):
x = 'D'
class E(C, D):
x = 'E'
obj = E()
obj.x = 'obj'
查找顺序:obj->-E->C->A->D->B->object
菱形继承:即子类有多个父类,而多个父类的分支在最后汇聚到一点,就是汇聚到一个父类时,这就是菱形继承。
在菱形继承的情况下,经典类与新式类就不一样了。
经典类:深度优先(一条路走到黑,从左往右,一个一个分支查找,在第一条分支就找到了顶层类)
新式类:广度优先(从左往右找,找到顶层类时停下,然后掉头找下一个分支,直到最后一条分支才会找到顶层类。
五.继承原理
对于你定义的每一个类,python会自动计算一个方法解析顺序(MRO)列表,这个MRO列表就是简单的所有基类的线性顺序列表,而这个列表是通过c3算法实现的
它 实际上是和合并了所有基类的MRO列表并遵循以下三条原则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表的顺序被检查
3.如果对下一个类存在两个及以上合法的选择,选择第一个父类
使用:类名后+.mro()
六.在子类定义过程中重用父类属性的两种方式
方式一:
指名道姓的调用父类的方法,与继承无关。类名.属性名
调用数据属性就是调用数据属性
调用函数属性时,对于父类来说就是一个普通的函数,有几个参数就要传几个参数。
方式二:
使用super()
super()会产生一个特殊的对象,这个对象专门访问父类的属性。
按照继承的关系,完全参照MRO列表
在python2中,super(自己类名,自己对象名)
在python3中,super(),会自动传值
强调:不要用眼看,查一下MRO列表就一目了然了
class A:
def f1(self):
print('A.f1')
super().f2()
class B:
def f2(self):
print('B.f2')
class C(A,B):
def f2(self):
print('C.f2')
obj=C()
obj.f1()
print(C.mro())
结果:
A.f1
B.f2
MRO列表:
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
完全按照MRO列表查找!!!