面向对象之继承与派生
1、初识继承
什么是继承
继承是一种新建类的方式,新建的类称之为子类,被继承的类称之为基类、父类、超类
继承描述的是一种“遗传”的关系:子类可以重用父类的属性
在python中的继承注意两点:
1. 在python中支持一个子类同时继承多个父类,
2. python中类分为两种:
新式类:但凡继承object的类,以及该类的子类。。。都是新式类
在python3中一个类如果没有继承人类类,默认继承object类,即python3中所有的类都是新式类
经典类: 没有继承object的类,以及该类的子类。。。都是经典类
在python2中才区分新式类与经典类
为何要用继承
1. 减少代码冗余
如何用继承
class Parent1(object): pass # print(Parent1.__bases__) class Parent2: pass class Subclass1(Parent1,Parent2): pass print(Subclass1.__bases__)
1、如何利用继承减少代码冗余???
继承解决的是类与类之间的代码冗余问题,一定是一个类是另外一个类的子类
继承关系的查找
总结对象之间的相似之处得到类,总结类与类之间的相似之处就得到了类们的父类
class OldboyPeople: school='Oldboy' class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex self.score=0 def choose_course(self): print('%s is choosing course' %self.name) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level): self.name=name self.age=age self.sex=sex self.level=level def score(self,stu,num): stu.score=num
stu1=OldboyStudent('李特丹',18,'female')
OldboyPeople.__init__(tea1,'egon',18,'male',10)
class OldboyPeople: school='Oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex self.score=0 def choose_course(self): print('%s is choosing course' %self.name) class OldboyTeacher(OldboyPeople): # def __init__(self,name,age,sex,level): # self.name=name # self.age=age # self.sex=sex # self.level=level def score(self,stu,num): stu.score=num stu1=OldboyStudent('李特丹',18,'female') #OldboyPeople.__init__(stu1,'李特丹',18,'female') print(stu1.__dict__) tea1=OldboyTeacher('egon',18,'male') ##OldboyPeople.__init__(tea1,'egon',18,'male',10)
继承的查找顺序
单继承背景下属性查找的顺序:对象-》对象的类-》父类-》。。。
class Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1() #obj.f1() class Bar(Foo): def f1(self): print('Bar.f1') obj=Bar() obj.f2() ''' Foo.f2 Bar.f1 '''
多继承背景下属性查找的顺序:对象-》对象的类-》按照从左往右的顺序一个一个的分支找
# #第四层 class I: x='I' pass #第三层 class E: x='E' pass # class F(I): x='F' pass # class H: x='H' # # # 第二层 class B(E): x='B' pass # class C(F): x='C' pass # class D(H): x='D' pass # # #第一层 class A(B,C,D): x='A' pass # obj=A() obj.x=111 print(obj.x)
继承实现的原理(可恶的菱形问题)
在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)
如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性
如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类