Python课程回顾(day22)
类和对象之继承
1.什么是继承?
继承在我们人类现实世界中可以形容为一种遗传,就像孩子与爸爸之间的关系,爸爸可以将所有事物传给孩子的意思..
而在我们的python中之前也提到过一种继承,是在logging模块里说过的,它跟我们的现实世界恰好相反,是父类继承子类的一种继承
今天我们所说的这种继承是类和对象中的继承,在程序中继承是一种新建子类的方式,新创建的类被称之为子类/派生类,被继承的类称之为父类/基类/超类,而新创建的子类则可以重用到父类的属性
2.为何要用继承?
假设我们的父类有多个子类,而多个子类都要用到相同一段功能,这时候就可以将这段功能放置父类内,不仅子类也可以使用代码,还减少了代码冗余的现象
3.如何使用继承?
如下:在继承类的括号内加上被继承类的类名即完成继承,而在python中又分为单继承与多继承的特点
class Parent1: pass class Parent2 pass class Sub1(Parent1): # 继承Parent1 pass class Sub2(Parent1, Parent2): # 继承Parent1与Parent2 pass
print(Sub1.__bases__)
print(Sub2.__bases__) # 使用__bases__查看当前的被继承类(父类)
python2与python3继承关系的区别
python2与python3在继承上最大的区别就在于是否继承了object,object也是一个类,是python内部封装好的一些个功能,而在python2中有时是用不到继承object的,但在python3中,默认会直接继承object.总的来说,继承的类型分为两大类:
新式类:但凡继承了object类的子类以及子子类...,都称之为新式类.
经典类:但凡没有继承object类的子类以及子子类...,都称之为经典类
继承的应用1:
class Oldboy: school = 'oldboy' pass class Students(Oldboy): def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def choose_class(self): print('%s is choosing class' % self.name) class Teacher(Oldboy): def __init__(self, name, age, gender, level, salary): self.name = name self.age = age self.gender = gender self.level = level self.salary = salary def score(self, stu, num): stu.num = num print('%s老师给%s同学打了%s分' % (self.name, stu.name, num)) stu = Students('孔令飞', 23, 'male') teac = Teacher('egon', 26, 'male', 10, 10000) print(stu.school) # 继承之后可以查找父类的属性 print(teac.school) # 继承之后可以查找父类的属性
继承的应用2:
在子类派生出的新功能中如何重用父类的功能:
方式一:指名道姓的访问某一类中的函数,与继承无关
class Oldboy: school = 'oldboy' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Students(Oldboy): def choose_class(self): print('%s is choosing class' % self.name) class Teacher(Oldboy): def __init__(self, name, age, gender, level, salary): Oldboy.__init__(self, name, age, gender) # 直接调用父类的init,减少重复代码,产生对象(直接使用Oldboy内的init函数,与继承无关) self.level = level # 为其对象添加新的属性 self.salary = salary def score(self, stu, num): stu.num = num print('%s老师给%s同学打了%s分' % (self.name, stu.name, num)) stu = Students('孔令飞', 23, 'male') # 此时调Students等同于调Students内的init函数,但Students内没有就去父类Oldboy找 # print(stu.__dict__) # 证明子类确实重用父类的init函数 teac = Teacher('egon', 26, 'male', 10, 10000) stu.choose_class() teac.score(stu,100)
属性查找(方式2的前提):
# 在单继承背景下,无论是经典类还是新式类属性查找顺序都是一样的 # 例: class Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') # 2.打印一 self.f1() # 3.打印成功之后又调用自身的f1,若自身内有则打印 class Bar(Foo): def f1(self): print('Bar.f1') # 4.打印二 obj = Bar() obj.f2() # 1.首先当前对象内没有f2,然后去类找,类也没有,则去父类
# 在多继承背景下,如果一个子类继承了多个分支, # 但是多个分支没有汇聚到一个非object类 # (汇聚到一点则称之为菱形继承----->(从最低点向上分支又进行汇聚)) # 无论新式类还是经典类属性查找顺序都是一样的 # 它会按照从左到右的分支一个一个查找下去 class E: xxx = 'E' class F: xxx = 'F' class D: xxx = 'D' class C(F): xxx = 'C' class B(E): xxx = 'B' class A(B, C, D): # 从左到右一个分支一个分支的去找,若分支内也存在继承关系,则会查找完毕后再进入下一个分支查找 xxx = 'A' obj = A() obj.xxx = 1 print(obj.xxx) # 查找顺序为:obj内-->A-->B-->E-->C-->F-->D-->object
# 在多继承背景下,如果一个子类继承了多个分支, # 而且多个分支汇聚到了一个非object类
# 新式类:广度优先查找 # 经典类:深处优先查找 class G: pass class E(G): xxx = 'E' class F(G): xxx = 'F' class D(G): xxx = 'D' class C(F): xxx = 'C' class B(E): xxx = 'B' class A(B, C, D): xxx = 'A' obj = A() obj.xxx = 1 print(obj.xxx) # 深度优先查找顺序为:当前对象内-->类-->A-->B-->E-->G-->C-->F-->D # 广度优先查找顺序为:当前对象内-->类-->A-->B-->E-->C-->F-->D-->G-->object
print(A.mro()) # 根据c3线性化算法算出来的一种属性查找方法,结果是一个列表,会按照列表内的顺序依次进行查找,只要在类定义完成时c3算法会自动算出属性的查找方法
c3算法无论是否为菱形继承都会算出属性查找方法
继承的应用2:
方式二:super方法
在python3中,super是可以不用传入参数的,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中的属性的
super会严格按照当前类的mro列表依次进行属性查找
class Oldboy: school = 'oldboy' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Students(Oldboy): def choose_class(self): print('%s is choosing class' % self.name) class Teacher(Oldboy): def __init__(self, name, age, gender, level, salary): super(Teacher,self).__init__(name,age,gender) # super方法得到的对象就是专门查找父类属性的,所有直接调用父类的__init__函数来为teac添加属性 self.level = level self.salary = salary def score(self, stu, num): stu.num = num print('%s老师给%s同学打了%s分' % (self.name, stu.name, num)) stu = Students('孔令飞', 23, 'male') # print(stu.__dict__) teac = Teacher('egon', 26, 'male', 10, 10000) stu.choose_class() teac.score(stu,100)