ITPub博客

首页 > > > Python每天一分钟:调用多个父类的构造函数/方法引发的BUG与修复

Python每天一分钟:调用多个父类的构造函数/方法引发的BUG与修复

作者:bluetooth 时间:2019-10-09 09:14:24 0 删除 编辑

在python的类编程方法中,子类(派生类)会继承父类的构造方法,当创建子类对象时,会自动调用父类的构造方法。

多个父类构造函数的调用

若子类继承于多个父类,那么子类对象在创建时会按照子类定义中的父类继承顺序调用父类的构造方法( __init__()),如python中类的继承顺序如下:

子类定义:

类C:类B,类A

此时在创建C的实例时:c=C ( )

会优先调用类B的构造函数,然后再调用类A的构造函数

一个bug:下图中代码问题的根源是什么?

但在实际应用中,开发人员一般都会重写类的构造方法,那么继承于多个父类的子类在实例化时就会遇到父类构造函数初始化不全的问题,如以下代码:

案例代码

解析:

上图程序第 17 行代码定义的man类,继承于people和chinese两个父类,因此,在实例化man类时,将按其继承顺序优先调用 people类的构造方法(因为继承顺序排在首位),此时只有父类people的构造方法__init__(self,color)会被调用从而初始化color 变量,故执行p.human()来访问父类变量color是没有问题的。

但是如果放开第22行代码,通过p.infor()来访问第二个父类chinese的实例变量country和city时就会引发错误,因为在用people类的构造方法创建man对象时,并未传值给 chinese类的构造方法来初始化实例变量:country和city,因此运行此行代码时会报错如下:

问题根源

假如我们做如下更改,将man类的定义改为:

class man(chinese, people)

此时man类将优先调用 chinese类的构造方法,那么在第20行代码中创建man对象时必须传入两个参数:

p= man('中国','上海')

上述代码明显是调用chinese父类的构造方法,并初始化了chinese类中的country和city两个实例变量,此时会遇到相同的问题:

people类中的构造方法没有被调用,导致color实例变量未被初始化,因此,运行第21行代码会报错,而第22行代码则可以正常执行。

那么有什么办法让man在实例化时可以同时初始化两个父类中的实例变量呢?

答案是:在man中定义自己的构造方法!

Bug的修复方法

解决上述bug的方法就是在子类man中定义自己的构造方法,即重写父类的构造方法,但必须遵循Python的规则:

若在子类中重写父类的构造方法,那么子类的构造方法必须调用父类的构造方法!

python中子类构造方法调用父类构造方法的方式有两种:

通过未绑定方法逐个调用多个父类的构造方法。点击了解:未绑定方法与绑定方法

通过 super() 函数来调用父类的构造方法。

下面我们分别演示上述两种bug修复方式的具体代码实现!

修复方式一:通过未绑定方法逐个调用多个父类的构造方法

直接看代码,修复方式简单明了,大家一看便知,不做赘述:

未绑定方法调用多个父类构造函数

修复方式二:通过 super() 函数来调用父类的构造方法

首先来了解super()函数,全在图里了:

super函数详解

上图如果不清晰,读者可自行搜索查阅super函数的使用,需要注意的是:

当子类继承于多个父类时,super() 函数只可用于调用第一个父类的构造函数,其余父类的构造函数只能使用未绑定的方式调用。

下面直接看修复代码:

super方式修复

总结

python中关于多个父类构造函数的调用不同的开发人员有不同的方法,本文只是介绍了两种常见的修复方式,个人推荐使用“通过未绑定方法逐个调用多个父类的构造方法”,这种方法易于理解,易于实现!

希望本文有助于读者的学习,工作!最后感谢您的阅读!

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/3402/viewspace-3132853/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-07-11

  • 博文量
    280
  • 访问量
    20987