什么是继承
继承是一种新建类的方式,新建的类称之为:子类/派生类,被继承的类称之为:父类/基类/超类
继承的特性
1.python支持多继承(一个子类可以同时继承多个父类)
2.子类继承父类,可以重用父类的属性 --->减少了类与类之间的代码冗余
3.从继承的角度来看,python分为新式类和经典类
新式类:继承object类的类以及他的子类(在python3中都默认继承object类,也就是说python3中只有新式类)
经典类:没有继承object的类,在python2中新式类需要显式的继承,否则为经典类
新式类和经典类的区别?
1.从继承特性的角度看,继承object类的新式类可以重用object父类的属性,而经典类则不行
2.从属性查找的角度看,新式类与经典类在菱形继承问题上属性的查找顺序有所区别
继承之属性查找
对于单继承:对象自己---->产生对象的类----产生对象的类的父类--->父类的父类(新式类包括object类).....,没有报错....
对于非菱形的多继承(一个子类同时继承了多个父类,这些父类最终没有继承同一个非object类的类):
对象自己--->产生对象的类--->按照继承关系,从左到右,一条分支一条分支的查找,没有就报错,这里新式类与经典类无差
对于菱形继承问题(一个子类同时继承了多个父类,而这些父类最终又共同继承了同一个非object类的类):
新式类:广度优先---->按照继承关系从左至右,一条分支一条分支的查找,But,只有在最后一条分支才会去找那个被多个父类共同继承的最终类(非object类)
经典类:深度优先------->按照继承关系从左至右,一条分支一条分支的查找,But,在第一条分支就会去查找那个被多个父类共同继承的最终类
class Foo: def f1(self): print('foo.f1') def f2(self): print('foo.f2') self.f1() class Bar(Foo): def f1(self): print('bar.f1') f = Bar() f.f2() #foo.f2 #bar.f1
继承原理:
对于你定义的每一个类来说,python通过C3算法得出一个方法解析顺序MRO列表,这个列表就是简单的所有基类的线性顺序列表,python为了实现继承,会根据这这MRO列表从左至右查找基类,直到查到拥有这个属性的基类为止
这个MRO列表遵循下面三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
此外,python为我们内置了一个查看MRO列表的内置方法
class C(B, A): pass print(C.mro()) #实际上就是print(C.__mro__) [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
在子派生的新方法中重用父类方法的两种途径:
方法一:指名道姓的方式(本质就是函数的调用,无自动传值的效果,与继承无关)
class People: def __init__(self,name,age): self.name = name self.age = age class Student(People): def __init__(self,name,age,student_id): People.__init__(self,name,age) self.student_id = student_id
方式二:使用super(自己的类名,对象名),它会得到一个特殊的对象,该对象专门用于访问父类的属性(该父类是指触发属性查找的类的父类),这是一种严格依赖于继承关系的方法,完全参照MRO列表
class B: def f1(self): print('B.f1') def f2(self): print('B.f2') super().f1() class C(B, A): def f1(self): print('C.f1') print(C.mro()) c = C() c.f2() #(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) #B.f2 #A.f1