继承是一种新建类的方式,新建的类称为子类/派生类,被继承的类称为父类/基类/超类
一.特点
- 子类可以重用/遗传父类的属性
- 一个子类可以继承多个父类
- 在继承的背景下,分为新式类与经典类.
二.新式类
但凡继承了object的类,以及继承了该类的子类,统称为新式类,python3会默认继承object类,所以python3中都为新式类
三.经典类
没有继承object的类为经典类,python2由于不会默认继承object类,故在python2中才区分经典类与新式类
四.派生
指在子类中自定义自己的属性,如果定义的属性与父类重名,那以自己的属性为准
五.作用
减少类与类间代码冗余量
六.在子类派生的新方法中重用父类功能的方式之一
指名道姓引用某一个类中的函数
class OldboyPeople:
school='oldboy'
def __init__(self,name):
self.name=name
class OldboyStudent:
def __init__(self,name,score)
OldboyPeple.__init__(self,name)
self.score=score
class OldboyTeacher:
def __init__(self,name,level):
OldboyPeople.__init__(self,name)
self.level=level
stu1=OldboyStudent('王五',80)
Tea1=OldboyTeacher('张三',10)
总结:
- 与继承无关
- 由于是直接访问类中函数,故不会自动传值
七.在单继承背景下的属性查找
查找优先级:对象→对象的类→父类→父类
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')
obj=Bar()
obj.f2()
'''
>>Foo.f2
>>Bar.f1
'''
运行流程:调用对象f2函数,由于对象的类中,故去该类的父类中找,找到之后输出Foo.f2,然后遇到调用函数self.f1(),这个时候还是优先回到对象的类中寻找,如没有才会又去对象的父类中找,故最终结果为Bar.f1
八.在多继承背景下的属性查找
当一个子类继承多个多个分支(多个分支没有共同继承一个非object的类)
查找优先级:对象→对象的类→然后按照从左到右的顺序顺着每个分支找下去
A | ||
↑ | ||
B | C | |
↑ | ↑ | |
E | F | G |
↖ | ↑ | ↗ |
H(E,F,G) |
表格查找顺序:H→E→B→A→F→C→G→object
九.菱形继承问题
- 新式类:使用广度优先查找,查找方法是从左到右,在最后一个分支才去查找顶级类
- 经典类:使用深度优先查找,查找方法与广度区别是在第一个分支就查找到了顶级类,之后就不再查找顶级类
A | ↖ | |
↑ | ↖ | ↑ |
B | C | ↑ |
↑ | ↑ | ↑ |
E | F | G |
↖ | ↑ | ↗ |
H(E,F,G) |
表格查找顺序:
- 新式类:H→E→B→F→C→G→A
- 经典类:H→E→B→A→F→C→G
十.在子类派生出的新方法中重用父类功能的方式二
使用super函数
当调用super函数时会得到一个特殊对象,作用是访问父类中的属性,访问顺序参照mro列表
使用区别:
- python2:super(自己的类名,自己的对象)
- python3:super()自动调入
class OldboyPeople:
school='oldboy'
def __init__(self,name):
self.name=name
class OldboyStudent(OldboyPeople):
def __init__(self,name,score):
super().__init__(self,name) #Python2中:super(OldboyStudent,self).__init__(self,name)
self.score=score
stu1=OldboyStudent('张三',80)