一、类的继承 1、什么是继承? 继承一种新建类的的方式,在python中支持一个儿子继承多个爹 新建的类称为子类或者派生类, 父类又可以称为基类或者超类 子类会”遗传“父类的属性,从而解决代码重用问题 2、为什么要用继承 减少代码冗余 class ParentClass1: pass class ParentClass2: pass class Subclass1(ParentClass1): pass class Subclass2(ParentClass1,ParentClass2): pass print(Subclass1.__bases__) print(Subclass2.__bases__) 了解: 在python2中有经典类与新式类之分,在python3中全都为新式类。 3. 继承与抽象: 继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承 抽象即抽取类似或者说比较像的部分。 继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。 注意: 属性引用,会先从实例中找然后去类中找,然后再去父类中找...直到最顶级的父类。知道伐找不到才会报错 4.派生: 当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是, 一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。 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 elf.age = age elf.sex = 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) 派生中重新调用父类功能方法一:指名道姓地调用(与继承没有关系) 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): 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) 注意: 此种调用与调用普通函数无异了,因此即便是self参数也要为其传值。 派生中重新调用父类功能方法一:super()调用(严格依赖于继承) super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性 了解: 在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) # super()调用 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) 强调:二者使用哪一种都可以,但最好不要混合使用 5. 新式类与经典类 1、新式类: 继承object的类,以及该类的子类,都是新式类 在python3中,如果一个类没有指定继承的父类,默认就继承object 所以说python3中所有的类都是新式类 2、经典类(只有在python2才区分经典类与新式类): 没有继承object的类,以及该类的子类,都是经典类 print(object) class Foo(object): pass class Bar(Foo): pass print(Foo.__bases__) print(Bar.__bases__) 6. 多继承下属性查找 在菱形继承的背景下,查找属性 1、经典类:深度优先 2、新式类:广度优先 如果继承关系为非菱形结构, 则会按照先找第一条分支,然后再找第二条分支顺序直到找到我们想要的属性 print(F.mro()) # .mro()通过一个C3线性化算法来实现简单的所有基类的线性顺序列表 为了实现继承,python会 在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 class A: def test(self): super().test() class B: def test(self): print('from B') class C(A,B): pass c=C() c.test() A没有继承B,但是A内super会基于C.mro()继续往后找 了解: 即使没有直接继承关系,super仍然会按照mro列表继续往后查找是否有匹配的属性