面向对象之继承
一、继承
1、什么是继承?
继承是一种新建类的方式,在python中支持一个儿子继承多个爹
新建的类称为子类或派生类
父类又可以称为基类或超类
子类会‘’遗传‘’父类的属性
2、为什么要继承?
减少代码冗余
3、怎么用继承?
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'>)
在python2中有经典类与新式类之分
在python3中全部为新式类
二、寻找继承关系
1、继承是类与类之间的关系,寻找这种关系需要先抽象再继承
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class OldboyTeacher(OldboyPeople): def change_score(self): print('teacher %s is changing score'%self.name) class OldboyStudent(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)#egon print(stu1.name)#alex
三、基于继承属性的查找
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 change_score(self): print('teacher %s is changing score'%self.name) tea1=OldboyTeacher('egon',18,'male') print(tea1.__dict__)#{'name': 'egon', 'age': 18, 'sex': 'male'} print(tea1.name)#egon print(tea1.school)#oldboy print(tea1.change_score) #<bound method OldboyTeacher.change_score of <__main__.OldboyTeacher object at 0x00000236244C7A58>> print(tea1.f1) #<bound method OldboyPeople.f1 of <__main__.OldboyTeacher object at 0x00000271923D7A58>> class Foo: def f1(self): print('Foo.f1') def f2(self):#self=obj print('Foo.f2') self.f1()#obj.f1() class Bar(Foo): def f1(self): print('Bar.f1') obj=Bar() # print(obj.__dict__) obj.f2()#Foo.f2,Bar.f1
四、派生
什么是派生?
子类定义自己新的属性,如果与父类同名,以子类自己的为准
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) tea1.f1()#儿子的f1 print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary)#egon 18 male 9 3.1
五、重用父类
在子类派生出的新方法中重用父类
方式一:指名道姓的调用(其实与继承是没有关系的)
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): print(''' -----------个人信息----------- 姓名:%s 年龄:%s 性别: %s '''%(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): OldboyPeople.__init__(self,name,age,sex) self.level=level self.salary=salary def tell_info(self): OldboyPeople.tell_info(self) print(''' 等级:%s 薪资:%s '''%(self.level,self.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 tea1.tell_info() ''' -----------个人信息----------- 姓名:egon 年龄:18 性别: male 等级:9 薪资:3.1 '''
方式二:super()调用(严格依赖于继承)
super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性
在python2中,super(自己的类名,self)
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): print(''' -----------个人信息----------- 姓名:%s 年龄:%s 性别: %s '''%(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): # OldboyPeople.__init__(self,name,age,sex) super().__init__(name,age,sex) self.level=level self.salary=salary def tell_info(self): # OldboyPeople.tell_info(self) super().tell_info() print(''' 等级:%s 薪资:%s '''%(self.level,self.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 tea1.tell_info() ''' -----------个人信息----------- 姓名:egon 年龄:18 性别: male 等级:9 薪资:3.1 '''
六、经典类与新式类
1、新式类(广度优先):
继承object的类,以及该类的子类都是新式类
在python3中,如果一个类没有指定的父类,默认就是继承object
所以在python3中所有的类都是新式类
2、经典类(深度优先,只有python2中才区分经典类与新式类):
没有继承object的类,以及该类的子类都是经典类
#新式类&经典类 class Foo(object): pass class Bar(Foo): pass print(Foo.__bases__)#(<class 'object'>,) print(Bar.__bases__)#(<class '__main__.Foo'>,)
七、在多继承背景下的属性查找
在菱形继承的背景下:查找属性
1、经典类:深度优先(没有继承object的类以及子类)
2、新式类:广度优先(继承object的类以及子类)
八、super()依赖继承
super()会严格按照mro列表从当前查找的位置继续往后查找
class A: def test(self): print('A.test') super().test() class B: def test(self): print('from B') class C(A,B): pass c1=C() print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] c1.test() #A.test #from B