继承补充
什么是继承?
它是一种新建类的方式,继承了一个类,类中的属性和方法就在子类中
父类就是基类, 子类就是派生类
拓展: 开发工具IDE: vscode, pycharm, sumlinetext
开发Java: eclipse, myeclipse, idea
开发安卓: eclipse+adt, Androidstudio: 基于idea+adt改的
新式类: 只要继承了object类,就是新式类,Python3中默认继承object类,python2中,需要显示指定的继承object
经典类: 没有继承object的类,就是经典类,Python3中没有经典类,Python2中才会有
- class A(object):
- pass
- class B(A):
- pass
- # 查看类名
- print(B.__name__)
- 输出: B
- # 查看父类
- print(B.__bases__) # B的所有的父类
- 输出为(<class '__main__.A'>,)
二. 属性查找的菱形问题:
- class people
- school = 'peking university'
- class Teacher(people):
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Student(people):
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- stu1 = Student('bgon', 85, "python") # 实例化一个对象
- print(stu1.school) # 学生类中并没school这个属性,他在父类中定义的
- # 输出结果为: peking university
如果这样继承的话,那么问题就来了,如何重用父类的属性,属性的查找顺序是什么,又是如何重用父类的方法?
我们之前说过查找对象顺序是: 先找对象===>类中找===>父类中找===>报错,但是呢,今天不一样,在父类中继承了好几个,也就是多继承,那又是如何去寻找?
三. 重用父类的方法
- class people
- school = 'peking university'
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Teacher(people):
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Student(people):
- def __init__(self, name, age, couse)
- self.name = name
- self.age = age
- self.couse = couse
- stu1 = Student('bgon', 85, "python") # 实例化一个对象
- print(stu1.school) # 学生类中并没school这个属性,他在父类中定义的
上面继承中可以看出,代码出现了冗余,那我们如何重用父类的__init__方法呢,我们先看第一种方法: 指名道姓的使用(跟继承无关)
- class people
- school = 'peking university'
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Teacher(people):
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Student(people):
- def __init__(self, name, age, couse)
- people.__init__(self, age,name)
- self.couse = couse
方式二: 通过super关键字
- class people
- school = 'peking university'
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Teacher(people):
- def __init__(self, name, age, level)
- self.name = name
- self.age = age
- self.level = level
- class Student(people):
- def __init__(self, name, age, couse)
- super().__init__(name, age)
- self.couse = couse
super()会按照mro列表拿到父类对象,对象来调用绑定方法, 不需要传递第一个参数(self),所以有__init__(name, age)
- class people
- school = 'peking university'
- def __init__(self, name, age)
- self.name = name
- self.age = agel
- class Teacher(people):
- pass
- class Student(people):
- pass
- stu1 = Student('bgon', 85) # 实例化一个对象
- print(stu1.school) # 学生类中并没school这个属性,他在父类中定义的
类实例化会自动调用__init__,如果类中没有,就去父类中去寻找
- 多层继承:
- class A:
- a = "AAAA"
pass- class B(A):
- a = "BBBB"
pass- class C(B):
- a = "CCCC"
pass- class D(C):
- a = "DDDD
pass- d = D()
- print(d, a)
- # 输出为DDDD
多继承:
- class A:
- a = "AAAA"
- pass
- class B:
- a = "BBBB"
- pass
- class C:
- a = "CCCC"
- pass
- class D(A, B, C):
- a = "DDDD
- pass
- d = D()
- print(d, a)
那上面的查找顺序又是怎样的呢? 首先还是先从自己找起,当D中没有a的值时,先找A,然后依次是,B,C
继承的菱形问题(显式的都继承一个类,不是object类):
在新式类和经典类的查找顺序是不一样的, 新式类的查找顺序是广度优先(从左侧开始,,一直往上找,找到菱形的顶点结束(不包括菱形顶点),继续下一个继承的父往上找,找到菱形的顶点结束(不包括菱形顶点)),经典类的查找顺序是深度优先(从左侧开始,,一直往上找,找到菱形的顶点结束(包括菱形顶点))==>一条道找到底然后再去广度上找
- 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__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 super是严格按照mro列表找
- #新式类继承顺序:F->D->B->E->C->A
- #经典类继承顺序:F->D->B->A->E->C
- #python3中统一都是新式类
- #pyhon2中才分新式类与经典类
所有的父类都到顶,才叫菱形问题,也就是说有一个总要继承object