1.什么是继承
继承是一种新建类的方式,新建的类称之为子类或者派生类,继承的弗雷称之为基类或超类。
# 在python中,一个子类可以继承多个父类。其他语言中,一个子类只能继承一个父类。
2.继承的作用
# 减少代码冗余。
3.如何实现继承
# 1)先确定谁是子类,谁是父类
# 2)在定义类子类时,class 子类名(父类名)
class Father1:
pass
class Father2:
pass
class Father3:
pass
class Sub(Father1,Father2,Father3):
pass
print(Sub.__bases__) # 打印Sub类的父类
1.如何寻找继承关系?
# 确定谁是子类
# - 野比大雄--->人子类--->动物父类
# - 喜羊羊 ---> 羊子类--->动物父类
# - 哈士奇 ---> 狗子类--->动物父类
# 确定谁是父类
# - 动物类是父类
# - 先抽象,再继承
# - 抽取对象之间相似的部分,总结出类
# - 抽取类之间相似的部分,总结出父类
# 代码冗余问题:
class Teacher:
school = 'oldboy'
country= 'China'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def modify_score(self):
print(f'{self.name} is modifying score...')
class Student:
school = 'oldboy'
country= 'China'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def check_score(self):
print(f'{self.name} is check score...')
# 使用继承
class SchoolPeople:
school = 'oldboy'
country= 'China'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
class Teacher(SchoolPeople):
def modify_score(self):
print(f'{self.name} is modifying score...')
class Student(SchoolPeople):
def check_score(self):
print(f'{self.name} is checking score...')
2.在继承背景下,对象属性的查找顺序
# 注意:程序的执行顺序是由上到下,父类必须定义在子类的上方。
#- 继承背景下,对象属性的查找顺序:
# - 首先在对象自己的名称空间
# - 对象所属的类的命名空间
# - 类的父类的命名空间,如果都找不到,就会报错。
3.类的派生
# 派生指的是:子类继承父类的属性和方法,并且派生出自己独有的属性和方法。若子类中的方法名与父类的相同,则父类的被覆盖。(也叫方法的重写)
class Foo:
def f1(self):
print('from Foo.f1...')
def f2(self):
print('from Foo.f2...')
self.f1() # self ==>bar_obj
class Bar(Foo):
def f1(self):
print('from Bar.f1...')
def func(self):
print('from Bar.func...')
bar_obj = Bar()
bar_obj.f2()
# output:from Foo.f2...
# from Bar.f1...
4.子类继承父类,派生出自己的属性和方法,并且重用父类的属性与方法
class SchoolPeople:
school = 'oldboy'
country= 'China'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
# Teacher类需要新增一个属性sal
# 代码更加冗余
class Teacher(SchoolPeople):
def __init__(self,name,age,gender,sal):
self.name = name
self.age = age
self.gender = gender
self.sal = sal
def modify_score(self):
print(f'{self.name} is modifying score...')
class Student(SchoolPeople):
def check_score(self):
print(f'{self.name} is checking score...')
解决方法:
class SchoolPeople:
school = 'oldboy'
country= 'China'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
# Teacher类需要新增一个属性sal
class Teacher(SchoolPeople):
# 方式1:
def __init__(self,name,age,gender,sal):
super().__init__(name,age,gender)
self.sal = sal
def modify_score(self):
print(f'{self.name} is modifying score...')
class Student(SchoolPeople):
# 方式2:
def __init__(self,name,age,gender,edu)
SchoolPeople.__init__(self,name,age,gender)
self.edu = edu
def check_score(self):
print(f'{self.name} is checking score...')
5.经典类与新式类:
# - 新式类:
# - 凡是继承object的类或子孙类都是新式类
# - 在python3中所有的类都默认继承object
# - 经典类:
# - 在python2中才会有经典类和新式类之分
# - 在python2中,凡是没有继承object的类,都是经典类
6.super()严格遵循mro继承
# 调用mro返回的是一个继承序列
# super的继承顺序严格遵循mro继承序列
# python3中提供了一个查找新式类查找顺序的内置方法。
# mro(),可以查看当前类的继承关系
class A:
def test(self):
print('from A...test')
class B:
def test(self):
print('from B...test')
class C(A,B):
pass
print(C.mro())
7.钻石继承(菱形继承)
'''
多继承情况下造成 “钻石继承”
mro的查找顺序:
- 新式类:
- 广度优先
- 经典类:
- 深度优先
'''
# 了解:
# 新式类:
class A(object):
# def test(self):
# print('from A')
pass
class B(A):
# def test(self):
# print('from B')
pass
class C(A):
# def test(self):
# print('from C')
pass
class D(B):
# def test(self):
# print('from D')
pass
class E(C):
# def test(self):
# print('from E')
pass
class F(D, E):
# def test(self):
# print('from F')
pass
# F-->D-->B-->E-->C-->A-->object
# print(F.mro())
obj = F()
obj.test()