Python高级编程之继承问题详解(super与mro)


Posted in Python onNovember 19, 2019

本文实例讲述了Python高级编程之继承问题。分享给大家供大家参考,具体如下:

多继承问题

1.单独调用父类:

一个子类同时继承自多个父类,又称菱形继承、钻石继承。

使用父类名.init(self)方式调用父类时:

例:

class Parent(object):
  def __init__(self, name):
    self.name = name
    print('parent的init结束被调用')
class Son1(Parent):
  def __init__(self, name, age):
    Parent.__init__(self, name)
    self.age = age
    print('Son1的init结束被调用')
class Son2(Parent):
  def __init__(self, name, gender):
    Parent.__init__(self, name)
    self.gender = gender
    print('Son2的init结束被调用')
class Grandson(Son1, Son2):
  def __init__(self, name, age, gender):
    Son1.__init__(self, name, age) # 单独调用父类的初始化方法
    Son2.__init__(self, name, gender)
    print('Grandson的init结束被调用')
gs = Grandson('grandson', 12, '男')

执行结果:

Python高级编程之继承问题详解(super与mro)

可以看出使用父类名.init(self)方式调用父类时,parent父类被调用了两次,此方法对于多继承不太合适。

2.MRO顺序:

上述代码,我们发现由于多继承情况,parent类被的属性被构造了两次,如果在更加复杂的结构下可能更加严重。

为了解决这个问题,Python官方采用了一个算法将复杂结构上所有的类全部都映射到一个线性顺序上,而根据这个顺序就能够保证所有的类都会被构造一次。

这个顺序就是MRO顺序。

MRO顺序采用C3算法广度优先遍历。

使用方法: 类名.mro()或类名.mro()

Python高级编程之继承问题详解(super与mro)

3.super调用父类:

使用super().init()方式调用父类时:

例:

class Parent(object):
  def __init__(self, name, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
    self.name = name
    print('parent的init结束被调用')
class Son1(Parent):
  def __init__(self, name, age, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
    self.age = age
    super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数
    print('Son1的init结束被调用')
class Son2(Parent):
  def __init__(self, name, gender, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数
    self.gender = gender
    super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数
    print('Son2的init结束被调用')
class Grandson(Son1, Son2):
  def __init__(self, name, age, gender):
    # 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍
    # 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因
    # super(Grandson, self).__init__(name, age, gender)
    super().__init__(name, age, gender)
    print('Grandson的init结束被调用')
gs = Grandson('grandson', 12, '男')
print(Grandson.__mro__)

运行结果:

Python高级编程之继承问题详解(super与mro)

parent父类只被调用了一次,super方法会按照MRO顺序调用下一个父类。

总结:

(1)MRO保证了多继承情况 每个类只出现一次

(2)super().init相对于类名.init,在单继承上用法基本无差

(3)但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次

(4)多继承时,使用super方法,对父类的传参数,是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错

(5)单继承时,使用super方法,不能全部传递,只能传父类方法所需的参数,否则会报错

(6)多继承时,相对于使用类名.init方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
基于python的汉字转GBK码实现代码
Feb 19 Python
python实现获取客户机上指定文件并传输到服务器的方法
Mar 16 Python
python获得linux下所有挂载点(mount points)的方法
Apr 29 Python
Python实现拷贝多个文件到同一目录的方法
Sep 19 Python
python2.7 json 转换日期的处理的示例
Mar 07 Python
详解Python requests 超时和重试的方法
Dec 18 Python
opencv与numpy的图像基本操作
Mar 08 Python
python微信撤回监测代码
Apr 29 Python
Python元组 tuple的概念与基本操作详解【定义、创建、访问、计数、推导式等】
Oct 30 Python
MATLAB数学建模之画图汇总
Jul 16 Python
python用tkinter实现一个简易能进行随机点名的界面
Sep 27 Python
Python序列化模块JSON与Pickle
Jun 05 Python
Python3 Tkinkter + SQLite实现登录和注册界面
Nov 19 #Python
Python csv文件的读写操作实例详解
Nov 19 #Python
Python高级property属性用法实例分析
Nov 19 #Python
wxPython之wx.DC绘制形状
Nov 19 #Python
python matplotlib拟合直线的实现
Nov 19 #Python
Python线程指南分享
Nov 19 #Python
wxpython+pymysql实现用户登陆功能
Nov 19 #Python
You might like
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
PHP4实际应用经验篇(7)
2006/10/09 PHP
php下图片文字混合水印与缩略图实现代码
2009/12/11 PHP
php5 non-thread-safe和thread-safe这两个版本的区别分析
2010/03/13 PHP
mac环境中使用brew安装php5.5.15
2014/08/18 PHP
PHP测试成功的邮件发送案例
2015/10/26 PHP
页面中body onload 和 window.onload 冲突的问题的解决
2009/07/01 Javascript
JavaScript中获取未知对象属性的代码
2011/04/27 Javascript
基于jquery扩展漂亮的下拉框可以二次修改
2013/11/19 Javascript
使用GruntJS构建Web程序之合并压缩篇
2014/06/06 Javascript
Javascript遍历table中的元素示例代码
2014/07/08 Javascript
jQuery向后台传入json格式数据的方法
2015/02/13 Javascript
javascript实现dom元素可拖动
2016/03/21 Javascript
浅谈jQuery中hide和fadeOut的区别 show和fadeIn的区别
2016/08/18 Javascript
BootstrapValidator超详细教程(推荐)
2016/12/07 Javascript
Ionic 2 实现列表滑动删除按钮的方法
2017/01/22 Javascript
ajax接收后台数据在html页面显示
2017/02/19 Javascript
vue2.0与bootstrap3实现列表分页效果
2017/11/28 Javascript
node Buffer缓存区常见操作示例
2019/05/04 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
JavaScript Array.flat()函数用法解析
2020/09/02 Javascript
Python下载指定页面上图片的方法
2016/05/12 Python
python中如何使用正则表达式的集合字符示例
2017/10/09 Python
PyQt5主窗口动态加载Widget实例代码
2018/02/07 Python
利用Django提供的ModelForm增删改数据的方法
2019/01/06 Python
利用pyshp包给shapefile文件添加字段的实例
2019/12/06 Python
教你如何用python操作摄像头以及对视频流的处理
2020/10/12 Python
python中@contextmanager实例用法
2021/02/07 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
美国汽车轮胎和轮毂销售网站:Tire Rack
2018/01/11 全球购物
瑞典多品牌连锁店:Johnells
2021/01/13 全球购物
结婚典礼主持词
2015/06/29 职场文书
基于Redis过期事件实现订单超时取消
2021/05/08 Redis
Python学习之迭代器详解
2022/04/01 Python
Mysql 文件配置解析介绍
2022/05/06 MySQL
Mysql中的触发器定义及语法介绍
2022/06/25 MySQL