第7.6节 Python中类的继承机制详述

在本章第一节,介绍了面向对象程序设计的三个特征:封装、继承和多态,前面章节重点介绍了封装和多态,由于Python语言是多态语言,对象的类型不再由继承等方式决定,而由实际运行时所表现出的具体行为来决定,因此不存在出于多态考虑来进行继承。但继承可以让子类获得超类(也称为父类、基类,老猿习惯称父类,文中可能会有超类和父类并存的说法,老猿也没有特地去统一,还请大家见谅)的全部功能,超类实现过的方法,子类不需要重新定义就能自动拥有。因此继承还是非常重要的。

一、    语法

要指定超类,可在class语句中的类名后加上超类名,并将其用圆括号括起,具体语法如下:

class 子类名 (超类1,超类2, ...):

       #类定义部分

从上面的语法格式来看,定义子类的语法非常简单,只需在原来的类定义后增加圆括号,并在圆括号中添加多个父类,即可表明该子类继承了这些父类。

实现继承的类被称为子类,被继承的类被称为父类(也被称为基类、超类)。父类和子类的关系,是一般和特殊的关系。

从子类的角度来看,子类扩展(extend)了父类;但从父类的角度来看,父类派生(derive)出子类。也就是说,扩展和派生所描述的是同一个动作,只是观察角度不同而已

二、    类继承方法的使用

1.    子类如果要继承父类的方法(含构造方法、析构方法),可以有2种方法:

1>    继承后不重写父类方法;

2>    重写父类方法,在子类的对应方法里显式地调用父类的方法。

2.    子类如果要重新父类方法(含构造方法、析构方法),但同时还需要父类的方法,可以在子类方法里显示调用父类的方法,同时在方法中再添加其他代码;

3.    子类方法中要显示调用父类方法的三种实现方式

1>    父类名.父类方法,这种方法需要注意,self参数必须传给父类方法;

2>    super().父类方法,这种方法调用不需要也不能传递self参数,由Python自动传入;

3>    super(子类名,self).父类方法,这种方法调用也不需要传递self参数。

以上三种方法,老猿推荐大家使用第二种,一是使用简单,不需要给出父类名或子类名,也不需要self参数传递,二是程序修改简单,如果父类或子类名修改无需修改相关代码。不过这种方法只有Python3以后才支持。

三、    类继承变量的使用

1.    父类定义的实例变量和类变量可以直接继承,可以在子类方法中直接访问,与访问自身定义的实例变量和类变量方式一样;

2.    如果子类和父类的不同实例方法都对某个实例变量进行赋值,但执行的顺序不同,哪个方法先执行就认为该实例是哪个类创建的实例变量,另外一个都可以对其进行访问。极端情况下,如果一个子类的实例变量定义后,在父类的实例方法可以访问该实例变量,无需在父类实例方法中先定义。老猿认为这种能力看起来使用灵活,但不建议使用,首先是因为这不符合父类、子类的设计原则,也不符合封装的原则,其次是容易带来问题,这种方式不符合类的使用者的思维模式,容易出现问题。

四、    说明

1.    在Python3后,如果在定义一个 Python 类时并未显式指定这个类的直接父类,则这个类默认继承 object 类。因此,object 类是所有类的父类,要么是其直接父类,要么是其间接父类;

2.    Python支持多继承,多继承的子类会继承多个超类所有的属性和方法。

1)    大部分面向对象的编程语言(除了 C++)都只支持单继承,而不支持多继承,这是由于多继承不仅增加了编程的复杂度,而且很容易导致一些莫名的错误;

2)    Python 虽然在语法上明确支持多继承,但通常推荐如果不是很有必要,则尽量不要使用多继承,而是使用单继承,这样可以保证编程思路更清晰,而且可以避免很多麻烦;

3)    如果多个超类以不同的方式实现了同一个方法(即有多个同名方法),必须在class语句中小心排列这些超类,因为位于前面的类的方法将覆盖位于后面的类的方法。

3.    一个类的基类可通过其特殊属性__bases__访问;

4.    多个超类的超类有相同方法时,查找特定方法或类变量时访问超类的顺序称为方法解析顺序(MRO),Python使用MRO算法按照类和实例属性的查找顺序去查找类变量。关于MRO算法请大家参考:https://blog.csdn.net/qq_34979346/article/details/83181353

本节介绍了Python中类中类的继承语法,以及在子类中怎么继承使用父类的变量和方法,有关内容涉及面较广,本节未举例进行说明,下节专门举例介绍。

老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。

欢迎大家批评指正,谢谢大家关注!

上一篇:python concurrent.futures.Threadpoolexcutor的有界队列和*队列


下一篇:4G模块ME3760_V2的拨号过程