7.2 继承与派生
7.21继承
1、什么是继承? 继承是一种新建类的的方式,在python中支持一个子类继承多个父类。新建的类称为子类或者派生类,父类又可以称为基类或者超类,子类会”遗传“父类的属性。
2、为什么要用继承 减少代码冗余
class ParentClass1: pass class ParentClass2: pass class Subclass1(ParentClass1): pass class Subclass2(ParentClass1,ParentClass2): pass print(Subclass1.__bases__) #(<class '__main__.ParentClass1'>,) print(Subclass2.__bases__) #(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
3、继承是类与类之间的关系,寻找这种关系需要先抽象再继承
class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyTeacher(OldboyPeople): #继承OldboyPeople类 def change_score(self): print('teacher %s is changing score' %self.name) class Oldboystudent(OldboyPeople): #继承OldboyPeople类 def choose(self): print('student %s choose course' %self.name) tea1 = OldboyTeacher('egon', 18, 'male') # 相当于OldboyTeacher.__init__(...) stu1=Oldboystudent('alex',73,'female') print(tea1.name,tea1.age,tea1.sex) #egon 18 male print(stu1.name,stu1.age,stu1.sex) #alex 73 female
7.22 派生
派生:子类定义自己新的属性,如果与父类同名,以子类自己的为准
class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def f1(self): print('爹的f1') class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): self.name=name self.age=age self.sex=sex self.level=level self.salary=salary def change_score(self): print('teacher %s is changing score' %self.name) def f1(self): print('儿子的f1') tea1 = OldboyTeacher('egon', 18, 'male',9,3.1) #传入6个参数,如果传入父类ze报错 print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary) #egon 18 male 9 3.1
7.23 在子类派生出的新方法中重用父类的功能
方式一:指名道姓地调用(与继承没有什么关系)
class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyTeacher(OldboyPeople): #可有可无 def __init__(self, name, age, sex, level, salary): # self.name = name # self.age = age # self.sex = sex OldboyPeople.__init__(self,name, age, sex)#用 OldboyPeople调用__init__的方式重用父类功能 self.level = level self.salary = salary tea1 = OldboyTeacher('egon', 18, 'male', 9, 3.1) print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary) #egon 18 male 9 3.1
方式二:super()调用(严格依赖于继承)
super ( ) 的返回值是一个特殊的对象,该对象专门用来调用父类中的属性,super()会严格按照mro列表从当前查找到的位置继续往后查找
了解:在python2中,需要super(自己的类名,self)
class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyTeacher(OldboyPeople): #必须有父类 def __init__(self, name, age, sex, level, salary): super(OldboyTeacher,self).__init__(name,age,sex)# OldboyPeople.__init__(self,name, age,sex) self.level = level self.salary = salary tea1 = OldboyTeacher('egon', 18, 'male', 9, 3.1) print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary) #egon 18 male 9 3.1
7.3 经典类与新式类
1、新式类: 继承object的类,以及该类的子类,都是新式类
在python3中,如果一个类没有指定继承的父类,默认就继承object,所以说python3中所有的类都是新式类
2、经典类(只有在python2才区分经典类与新式类):没有继承object的类,以及该类的子类,都是经典类
class Foo(): #在python3中 pass class Bar(Foo): pass print(Foo.__bases__) #(<class 'object'>,) print(Bar.__bases__) #(<class '__main__.Foo'>,)
7.34 在多继承背景下的属性查找
属性查找
obj.x 1、先从obj.__dict__ 2、对象的类.__dict__ 3、父类.__dict__ ..........
如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性
如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先
print(F.__mro__) # F.mro() #只有新式类才有这个属性可以查看线性列表,查看属性查找顺序,经典类没有这个属性