第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解

时间:2023-03-08 22:51:46
第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解

第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解

一、    引言

上两节介绍了构造方法的语法及参数,说明了构造方法是Python的类创建实例后首先执行的方法,并说明如果类没有重写构造方法,Python将会给出默认的__init__方法。上述介绍适用于自定义类没有自定义父类的情况,如果自定义类是从其他自定义类派生的,又会怎样呢?

二、    构造方法与继承

为了保障相关逻辑的正确性,在子类重写构造方法时,必须调用超类(继承的类)的构造方法,否则可能无法正确地初始化对象。

1.    子类在构造方法处理时,可以有两种方法:

1>    继承后不重写构造方法,此时子类直接继承了父类的构造方法;

2>    重写父类构造方法,在子类的构造方法里显式地调用父类的构造方法,对调用执行的具体代码位置没有要求,可以在子类构造方法的开始部分、中间部分或结尾部分都可以,主要看业务逻辑有没有要求。

这两种方法都可以确保子类继承父类时构造方法的正确性。

2.    子类里显示调用父类的构造方法的三种实现方式

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

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

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

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

三、    案例

1.    案例说明:

本节使用一个继承案例,超类为Vehicle(车),子类为car(小汽车),车只有3个实例变量:wheelcount(*数)、power(动力)、行驶总里程totaldistance,子类根据情况不同会有不同的实例变量,最多增加一个实例变量每公里油耗oilcostperkm(使用时错误,后面赋值时是按百公里油耗赋值的,特此说明)。为了聚焦问题,在类内都只定义构造方法,超类的类定义如下:

class Vehicle():
   def __init__(self,wheelcount, power):
       self.wheelcount,self.power,self.totaldistance = wheelcount,power,0

2.    案例1:子类不重写构造方法

1)    子类定义如下:

class Car(Vehicle):pass

此时应该继承父类的构造方法。

2)    没有写构造方法,不带参数执行实例定义,系统应报错

car=Car()

3)    按父类要求定义实例

car=Car(4,'汽油发动机') #带正确参数执行

4)    案例截图:

第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解
 

5)    案例总结:

子类继承父类构造方法,执行实例定义时直接执行该构造方法。

3.    案例2:子类重写构造方法但子类构造方法中不调用父类构造方法

1)    子类定义如下:

class Car(Vehicle):  #子类重写构造方法但子类构造方法中不调用父类构造方法
    def __init__(self,wheelcount, power,oilcostperkm):
        self.oilcostperkm = oilcostperkm
        print("In Car __init__:oilcostperkm=",self.oilcostperkm)。

2)    定义实例

car=Car(4,'汽油发动机',10)

3)    查看实例数据

car.__dict__ #查看实例自定义属性,应该只有oilcostperkm
car.wheelcount #查看实例的    wheelcount,应报错

4)    案例截图:

第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解
 

5)    案例总结:

子类重写构造方法,如果没有显示调用父类构造方法,则不会执行父类构造方法的相关代码。

4.    案例3:子类重写构造方法并调用父类构造方法

1)    子类定义如下:

class Car(Vehicle):  #子类重写构造方法但子类构造方法中不调用父类构造方法
    def __init__(self,wheelcount, power,oilcostperkm):
        self.oilcostperkm = oilcostperkm
        print("In Car __init__:oilcostperkm=",self.oilcostperkm)
        super().__init__(wheelcount, power) 

调用父类的构造方法,本例中用的这是一种老猿推荐的调用方法,还可以有下面两种调用方法:

Vehicle.__init__(self,wheelcount, power)
super(Car,self).__init__(wheelcount, power)

2)    定义实例和查看数据

car=Car(4,'汽油发动机',10) #应该执行两个构造方法
car.__dict__ #查看实例自定义属性,应该wheelcount, power,oilcostperkm都有
car.wheelcount #查看实例的    wheelcount,应正常给出

3)    案例截图:

第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解
 

4)    案例总结:子类重写构造方法,显示调用父类构造方法,相关实例变量都会正常初始化。

本节结合案例详细介绍了在继承情况下应该怎么实现子类的构造方法,内容比较简单但很重要,请大家注意。

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

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