面向对象编程有三大重要特征:封装、继承和多态。
继承
继承来源于现实世界,一个最简单的例子就是孩子会具有父母的一些特征,即每个孩子都会继承父亲或者母亲的某些特征,当然这只是最基本的继承关系,现实世界中还存在着更复杂的继承。继承机制实现了代码的复用,多个类公用的代码部分可以只在一个类中提供,而其他类只需要继承这个类即可。
在OOP程序设计中,当我们定义一个新类的时候,新的类称为子类(Subclass),而被继承的类称为基类、父类或超类(Baseclass、Superclass)。继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。其语法结构如下:
classFoo(superA,superB,superC....):classDerivedClassName(modname.BaseClassName):##当父类定义在另外的模块时
Python支持多父类的继承机制,所以需要注意圆括号中基类的顺序,若是基类中有相同的方法名,并且在子类使用时未指定,Python会从左至右搜索基类中是否包含该方法。一旦查找到则直接调用,后面不再继续查找。
#父类定义classpeople:def__init__(self,name,age,weight):self.name=nameself.age=ageself.__weight=weightdefspeak(self):print("%s说:我%d岁。"%(self.name,self.age))#单继承示例classstudent(people):def__init__(self,name,age,weight,grade):#调用父类的实例化方法people.__init__(self,name,age,weight)self.grade=grade#重写父类的speak方法defspeak(self):print("%s说:我%d岁了,我在读%d年级"%(self.name,self.age,self.grade))s=student(ken,10,30,3)s.speak()
Python3的继承机制
Python3的继承机制不同于Python2。其核心原则是下面两条,请谨记!
子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
根据父类定义中的顺序,以深度优先的方式逐一查找父类!
例一:
设想有下面的继承关系:
classD:passclassC(D):passclassB(C):defshow(self):print("iamB")passclassG:passclassF(G):passclassE(F):defshow(self):print("iamE")passclassA(B,E):passa=A()a.show()
运行结果是"iamB"。在类A中,没有show()这个方法,于是它只能去它的父类里查找,它首先在B类中找,结果找到了,于是直接执行B类的show()方法。可见,在A的定义中,继承参数的书写有先后顺序,写在前面的被优先继承。
那如果B没有show方法,而是D有呢?
classD:defshow(self):print("iamD")passclassC(D):passclassB(C):passclassG:passclassF(G):passclassE(F):defshow(self):print("iamE")passclassA(B,E):passa=A()a.show()
执行结果是"iamD",左边具有深度优先权,当一条路走到黑也没找到的时候,才换另一条路。可见,在这种继承结构关系中,搜索顺序是这样的:
例二:
那如果继承结构是这样的呢?类D和类G又同时继承了类H。当只有B和E有show方法的时候,无疑和上面的例子一样,找到B就不找了,直接打印"iamB"。但如果是只有H和E有show方法呢?
classH:defshow(self):print("iamH")passclassD(H):passclassC(D):passclassB(C):passclassG(H):passclassF(G):passclassE(F):defshow(self):print("iamE")passclassA(B,E):passa=A()a.show()
我们想当然地以为会打印"iamH",因为深度优先嘛。但是,打印的却是"iamE"!为什么?因为在这种情况下,Python的搜索路径是这样的:
那可能有同学会问,别的继承情况呢?你这两种继承图太简单了,不能代表所有!实际上其它的继承模式,仔细一解剖,都能划分成上面两种情况,比如下面的例子(箭头代表继承关系),B同时继承了C和F:
classD():passclassG():defshow(self):print("iamG")passclassF(G):passclassC(D):passclassB(C,F):passclassE(F):defshow(self):print("iamE")passclassA(B,E):pass
我们用图形来分析它,就是下面的样子:
super()函数:
我们都知道,在子类中如果有与父类同名的成员,那就会覆盖掉父类里的成员。那如果你想强制调用父类的成员呢?使用super()函数!这是一个非常重要的函数,最常见的就是通过super调用父类的实例化方法__init__!
语法:super(子类名,self).方法名(),需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数。
classA:def__init__(self,name):self.name=nameprint("父类的__init__方法被执行了!")defshow(self):print("父类的show方法被执行了!")classB(A):def__init__(self,name,age):super(B,self).__init__(name=name)self.age=agedefshow(self):super(B,self).show()obj=B("jack",18)obj.show()
以上就是Python继承的详解,私信回复,免费领取Python编程全套学习资料,包含全套视频教程、项目源码、学习路i线图等,赶快私信吧!