一.继承
继承是一种新建类的方式,新建的类从已有的类那里获得其已有的属性与方法,这个新建的类称之为子类,被继承的类称之为父类或/基类/超类
继承的特性:子类遗传父类的属性
在python中,一个子类可以同时继承多个父类,而且在继承背景下,python中的类分为两种:新式类与经典类
新式类:但凡继承了object的类,以及该类的子类,都是新式类
在python3中一个类即便是没有显式地继承任何类,默认就会继承object,所有在python3中所有的类都是新式类
经典类:没有继承object的类,以及该类的子类,都是经典类
在python2中才区分新式类与经典类
继承的出现是为了解决类与类之间的代码冗余
class Parent1:#创建父类 pass class Parent2:#创建父类 pass class Sub1(Parent1):#单继承,父类是Parent1 pass class Sub2(Parent2,Parent1):#多继承,父类是Parent2,Parent1 pass
二.利用继承解决代码冗余
在开发的过程中,如果定义两个类,而且两个类中的大部分内容都相同,我们不可能从头开始写一个类,这时候就可以使用继承的概念
class A: school = 'Oldboy' def __init__(self, name, age): self.name = name self.age = age class B(A): # def __init__(self, name, age, score=0): # self.name = name # self.age = age # self.score = score def choose_course(self): print('chooings') class C(A): # def __init__(self, name, age, level): # self.name = name # self.age = age # self.level = level def score(self, stu, num): stu.score = num # stu1 = B('hwt',18) # print(stu1.name) # # print(stu1.age) # # print(stu1.school) # # print(stu1.__dict__) # teacher1 = C('xiu',28) # print(teacher1.school)
三.在子类中派生的新方法中重用父类的功能
在子类中派生的新方法中重用父类的功能方式一:
指名道姓地引用某一个类中的函数
class Oldboy0: school = 'Oldboy' def __init__(self, name, age): self.name = name self.age = age class Oldboy1(Oldboy0): def __init__(self, name, age, score=0): Oldboy0.__init__(self, name, age) self.score = score def choose_course(self): print('chooings') class Oldboy2(Oldboy0): def __init__(self, name, age, level): Oldboy0.__init__(self, name, age) self.level = level def score(self, stu, num): stu.score = num stu1 = Oldboy1('hwt', 18) print(stu1.__dict__) teacher1 = Oldboy2('xiu', 28, 10) teacher1.score(stu1,100) print(stu1.score)
总结:
1.这种方式与继承无关
2.访问的是类的函数,没有自动传值的效果
在子类中派生的新方法中重用父类的功能方式二:
使用super()来实现在子类中派生的新方法中重用父类的功能,super()必须在类中用
使用方式:
在python2中:super(自己的类名,自己的对象)
在python3中:super()
调用该函数会得到一个特殊的对象,该对象专门用来访问父类中的属性,super是完全参照mro列表查找父类
class Oldboy0: school = 'Oldboy' def __init__(self, name, age): self.name = name self.age = age class Oldboy1(Oldboy0): def __init__(self, name, age, score=0): super(Oldboy1,self).__init__(name,age) self.score = score def choose_course(self): print('chooings') class Oldboy2(Oldboy0): def __init__(self, name, age, level): super(Oldboy2, self).__init__(name,age) self.level = level def score(self, stu, num): stu.score = num stu1 = Oldboy1('hwt', 18) print(stu1.__dict__) teacher1 = Oldboy2('xiu', 28, 10) print(teacher1.__dict__)
总结:
1.这种方式依赖继承的mro列表
2.访问的是绑定方法,有自动传值的效果
四.继承下的属性查找顺序
继承下的属性查找顺序分为两种:单继承下的属性查找与多继承下的属性查找
单继承下的属性查找:
对象-->对象的类中-->父类
class Foo: def f1(self): print('foo.f1') def f2(self): print('foo.f2') self.f1() class Bar1(Foo): def f1(self): print('bar1.f1') class Bar2: pass obj = Bar1() obj.f2()
多继承下的属性查找:
如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)
此时属性的查找优先级:对象->对象的类->按照从左往右的顺序一个分支一个分支查找
菱形继承问题:
新式类:广度优先查找,从左往右一个分支一个分支查找,在最后一个分支才去查找顶级类
经典类:深度优先查找,从左往右一个分支一个分支查找,在第一个分支才去查找顶级类
python专门为新式类内置了一个mro的方法,用来查看c3算法的计算结果
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中才分新式类与经典类