继承
一、什么是继承
继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。
二、继承的特点
1.继承描述的是事物的遗传关系,子类可以重用父类的属性
2.在Python中支持一个子类继承多个父类
3.Python类分为两种:新式类、经典类
(1)新式类:继承object的类,以及该类的子类。
(2)经典类:没有继承object的类,以及该类的子类。
在Python3中默认继承object类,所以Python3中都是新式类;在Python2中要继承object类必须手动继承,所以只有Python中才分新式类和经典类
三、单继承和多继承
class Parent1(): a = 3 class Parent2(): a = 3 class Sub1(Parent1): # 单继承,父类是Parent1,子类是Sub1 a = 2 pass class Sub2(Parent1,Parent2): # 多继承,父类是Parent1,Parent2,子类是Sub1 a = 2 pass
四、查看继承
利用__bases__方法可以查看子类的父类,只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类 class Parent1(): pass class Sub1(Parent1): pass print(Sub1.__bases__)
五、继承的作用
继承解决的是类与类之间的代码冗余问题,一定是一个类是另外一个类的子类
六、子类重用父类中的方法(派生)
1、派生:在子类中定义自己的属性,如果与父类的属性重名,那以自己的为准
2、在子类派生出的新方法中重用父类功能的方式一:指名道姓地访问父类中的函数
Foo.__init__(self,name,age) 不能自动传值,有几个参数就传几个
(1)该方式与继承无关
(2)没有自动传值的效果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class People(): 2 def __init__(self, name, age, sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 7 8 class Student(People): 9 def __init__(self, name, age, sex, score=0): 10 # 方式一 调用父类中的__init__函数 11 People.__init__(self, name, age, sex) 12 self.score = score 13 14 def choose(self): 15 print('%s choosing course' % self) 16 17 18 class Teacher(People): 19 def score(self, stu, score): 20 stu.score = score 21 22 23 stu = Student('张三', 12, 'male') 24 print(stu.__dict__) # __dict__可以查看对象的名称空间中的名字
3、在子类派生出的新方法中重用父类功能的方式二:super(),只能在子类中用
super().__init__(name,age) 自动传值
(1)在python2中:super(自己的类名,自己的对象)
在python3:super()
调用super()会得到一个特殊的对象,该特殊的对象是专门用来引用父类中的属性的,!!!完全参照mro列表!!!
(2)super()注意点:
a. 该方式与继承严格依赖于继承的mro列表,类名.mro() ===> 不管有没有继承关系,super()都是根据mro往后查找
b. 访问是绑定方法,有自动传值的效果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class People(): 2 def __init__(self, name, age, sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 7 8 class Student(People): 9 def __init__(self, name, age, sex, score=0): 10 super().__init__(name,age,sex) 11 self.score = score 12 13 def choose(self): 14 print('%s choosing course' % self) 15 16 17 class Teacher(People): 18 def score(self, stu, score): 19 stu.score = score 20 21 22 stu = Student('张三', 12, 'male') 23 print(stu.__dict__) # 查看对象的名称空间
七、继承背景下的属性查找
1、单继承背景下的属性查找
单继承背景下属性查找顺序:对象的名称空间------>对象的类的名称空间------->父类的名称空间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Foo: 2 x=333 3 pass 4 5 class Bar(Foo): 6 # x=222 7 pass 8 9 obj=Bar() 10 # obj.x=111 11 print(obj.x) # 333
2、多继承背景下的属性查找
多继承背景下属性查找的顺序:对象的名称空间------>对象的类的名称空间-------->按照从左往右的顺序一个一个的分支找下去
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 查找顺序是 obj-->A-->B-->E-->C-->F-->I-->D-->H 2 3 #第四层 4 class I: 5 # x='I' 6 pass 7 8 #第三层 9 10 class E: 11 # x='E' 12 pass 13 14 class F(I): 15 # x='F' 16 pass 17 18 class H: 19 x='H' 20 21 # 第二层 22 class B(E): 23 # x='B' 24 pass 25 26 class C(F): 27 # x='C' 28 pass 29 30 class D(H): 31 # x='D' 32 pass 33 34 #第一层 35 class A(B,C,D): 36 # x='A' 37 pass 38 39 obj=A() 40 # obj.x=111 41 print(obj.x)
八、继承顺序
1、在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)
2、如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性
下图中的继承关系,继承顺序就是A-->B-->E-->G-->C-->F-->D
3、如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先
(1)新式类(继承object的类): 广度优先查找,从左往右一个分支一个分支的查找,在最后一个分支才去查找顶级类
下图为新式类,继承顺序为:A-->B-->E-->C-->F-->D-->G-->object
(2)经典类(不继承object的类) : 深度优先查找,从左往右一个分支一个分支的查找,在第一个分支就查找顶级类
下图为经典类,查找顺序为:A-->B-->E-->G-->C-->F-->D