Python类的继承super相关原理解析


Posted in Python onOctober 22, 2020

看了网上许多关于super、mro、C3的介绍感觉没有一份很容易初学者理解的文档,直接看C3算法的话,比较难理解,也没必要,如果掌握一套规律的话,会轻松许多。我将网上这些博主的文章进行一个梳理总结,最后形成一套实用的关于super、mro、C3的理解介绍。

1、super

super()是一种将子类与父类联系起来的一种方法,子类通过继承父类,可以使用父类的方法和属性,也可以自己定义属于自己的方法和属性。super方法主要用在多继承中,在单继承时直接调用父类方法即可

下面这个是SGD源码的一部分,根据这份源码,

class SGD(Optimizer):
  def __init__(self, params, lr=required, momentum=0, dampening=0,
         weight_decay=0, nesterov=False):
    defaults = dict(lr=lr, momentum=momentum, dampening=dampening,
            weight_decay=weight_decay, nesterov=nesterov)
    if nesterov and (momentum <= 0 or dampening != 0):
      raise ValueError("Nesterov momentum requires a momentum and zero dampening")
    super(SGD, self).__init__(params, defaults)
  def __setstate__(self, state):
    super(SGD, self).__setstate__(state)
    for group in self.param_groups:
      group.setdefault('nesterov', False)

这是SGD类中的代码

有2点需要补充说明:

1、super联系父类的时候,需要调用父类的方法,包括所带的形参写完整,子类不够的形参需要额外加上

2、super联系父类的时候,不只是可以调用__init__,而且还可以调用父类其他的方法

3、python3可以写成super().__init__()这种写法了。

4、类都默认继承object类

另外,在super的使用过程中,还需要注意初始化对继承的影响:

1、子类继承父类,但不执行__init__方法,那么会自动继承父类属性。

2、子类继承父类,执行了__init__方法,且不调用super初始化父类构造函数,那么子类不会自动继承父类属性。

3、子类继承父类,执行了__init__方法,且调用了super初始化了父类的构造函数,那么子类会继承父类属性。

2、mro

Python的MRO,方法解析顺序,即在调用方法时,会对当前类以及所有的基类进行一个搜索,以确定该方法之所在,而这个搜索的顺序就是MRO。然后python会按照这个顺序去执行类之间的调用问题。

直接上例子

class A1():
  def __init__(self):
    print('A1')
    super().__init__()
class A2():
  def __init__(self):
    print('A2')
    super().__init__()
class A3():
  def __init__(self):
    print('A3')
    super().__init__()
class B1(A1, A2):
  def __init__(self):
    print('B1')
    super().__init__()
class B2(A2):
  def __init__(self):
    print('B2')
    super().__init__()
class B3(A2, A3):
  def __init__(self):
    print('B3')
    super().__init__()
class C1(B1):
  def __init__(self):
    print('C1')
    super().__init__()
class C2(B1, B2):
  def __init__(self):
    print('C2')
    super().__init__()
class C3(B2, B3):
  def __init__(self):
    print('C3')
    super().__init__()
class D(C1, C2, C3):
  def __init__(self):
    print('D')
    super().__init__()
d = D()
print(D.__mro__)

输出如下:

Python类的继承super相关原理解析

(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.B1'>, <class '__main__.A1'>, <class '__main__.C3'>, <class '__main__.B2'>, <class '__main__.B3'>, <class '__main__.A2'>, <class '__main__.A3'>, <class 'object'>)

那么这个程序是按怎么个顺序依次去执行那些方法呢,就是按照MRO中的顺序。

Python类的继承super相关原理解析

那么这个顺序如何自己手写出来呢?这就是C3算法,用于计算出MRO,得出执行顺序

3、c3算法

但是我在这里想告诉大家如何根据C3算法找出规律,从而自己写出顺序

还是上手例子,根据上面这个图,我们可以列出下面这个表,这个表示网上一个博主做的,可以说做出这张表就是做出了答案,那这张表“实际取出的类”怎么推出来的呢?我拿过来提炼出一些比较直接的规律

Python类的继承super相关原理解析

规律1:预查找父类按左边优先原则,比如第一行,当前类D的预查找父类选最左边的C1,而不是C2、C3。

规律2:当“预查找父类是否还有其他子类?同时又是最底层查找类的父类或父父类、父父父...类”没有的时候,直接选取预查找父类作为答案。当这项有类的时候,若“最底层的未查找父类”还有,则优先选它,若没有了,则选取这项类作为答案。

规律3:当预查找父类是object,只要最底层的未查找父类还有,就选这个最底层的未查找父类。若没有,则“预查找父类是否还有其他子类?同时又是最底层查找类的父类或父父类、父父父...类”有类的时候,就选这个类,没有的话,答案就是object

另外,

如何去画图:

1、子类永远画在父类的下面,并用有向箭头指向父类

2、遇到多继承则按代码中继承列表的顺序从左往右写。如果有多个子类继承了同一个父类,那么这个父类则放在它能够出现的所有位置中最左的位置。需遵循图里面的广度优先原则进行遍历(在广度优先原则的前提下又优先遍历左边的):

练习:

下面这个是网上的一份代码,看懂上面的规律以及如何画有向图之后,就可以顺利得出MRO的值了

class A:
  def __init__(self):
    print('A')
    
class B(A):
  def __init__(self):
    print('B')
    super().__init__()

class C(A):
  def __init__(self):
    print('C')
    super().__init__()

class D(A):
  def __init__(self):
    print('D')
    super().__init__()
    
class E(B, C):
  def __init__(self):
    print('E')
    super().__init__()


class F(C, D):
  def __init__(self):
    print('F')
    super().__init__()

class G(E, F):
  def __init__(self):
    print('G')
    super().__init__()

首先,画图

Python类的继承super相关原理解析

然后列表

当前类最底层未查找的父类预查找的父类预查找父类是否为object预查找父类是否有其他子类,同时又是最底层查找类的父类、父父类实际取出的类GE、FEnonoEEFBnonoBBFAno有,CFFnoCnonoCCnoAno有,DDDnoAnonoAAnoobjectyesnoobject

答案:

mro:GEBFC

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python使用dis模块把Python反编译为字节码的用法详解
Jun 14 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
May 25 Python
详解python string类型 bytes类型 bytearray类型
Dec 16 Python
解决Python 命令行执行脚本时,提示导入的包找不到的问题
Jan 19 Python
python实现对象列表根据某个属性排序的方法详解
Jun 11 Python
python下的opencv画矩形和文字注释的实现方法
Jul 09 Python
selenium+Chrome滑动验证码破解二(某某网站)
Dec 17 Python
python pip安装包出现:Failed building wheel for xxx错误的解决
Dec 25 Python
Python selenium文件上传下载功能代码实例
Apr 13 Python
Python3自定义http/https请求拦截mitmproxy脚本实例
May 11 Python
Python趣味挑战之教你用pygame画进度条
May 31 Python
python双向链表实例详解
May 25 Python
Python+OpenCV图像处理——打印图片属性、设置存储路径、调用摄像头
Oct 22 #Python
Python基于内置函数type创建新类型
Oct 22 #Python
python使用ctypes库调用DLL动态链接库
Oct 22 #Python
Python通过len函数返回对象长度
Oct 22 #Python
python 还原梯度下降算法实现一维线性回归
Oct 22 #Python
利用Pycharm + Django搭建一个简单Python Web项目的步骤
Oct 22 #Python
python处理写入数据代码讲解
Oct 22 #Python
You might like
PHP编程与应用
2006/10/09 PHP
解析PHP中intval()等int转换时的意外异常情况
2013/06/21 PHP
php制作圆形用户头像的实例_自定义封装类源代码
2017/09/18 PHP
extjs 学习笔记(一) 一些基础知识
2009/10/13 Javascript
深入理解Javascript中的循环优化
2013/11/09 Javascript
js解决弹窗问题实现班级跳转DIV示例
2014/01/06 Javascript
js实现带农历和八字等信息的日历特效
2016/05/16 Javascript
JavaScript遍历求解数独问题的主要思路小结
2016/06/12 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
2016/09/05 Javascript
微信小程序加载更多 点击查看更多
2016/11/29 Javascript
如何获取元素的最终background-color
2017/02/06 Javascript
JavaScript数据结构中串的表示与应用实例
2017/04/12 Javascript
在vue里使用codemirror遇到的问题
2018/11/01 Javascript
JavaScript惰性载入函数实例分析
2019/03/27 Javascript
微信小程序实现获取小程序码和二维码java接口开发
2019/03/29 Javascript
JS实现json数组排序操作实例分析
2019/10/28 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
微信小程序实现日历小功能
2020/11/18 Javascript
[10:34]DOTA2上海特级锦标赛全纪录
2016/03/25 DOTA
Python中字典(dict)合并的四种方法总结
2017/08/10 Python
python django下载大的csv文件实现方法分析
2019/07/19 Python
对Python _取log的几种方式小结
2019/07/25 Python
Python实现检测文件的MD5值来查找重复文件案例
2020/03/12 Python
Saucony澳大利亚官网:美国跑鞋品牌,运动鞋中的劳斯莱斯
2018/05/05 全球购物
澳大利亚婴儿礼品公司:The Baby Gift Company
2018/11/04 全球购物
Lulu Guinness露露·吉尼斯官网:红唇包
2019/02/03 全球购物
大学生自我鉴定范文
2013/12/28 职场文书
公司门卫工作职责
2014/06/28 职场文书
ktv好的活动方案
2014/08/17 职场文书
学用政策心得体会
2014/09/10 职场文书
解除劳动合同协议书范本
2014/09/13 职场文书
2015年12.4全国法制宣传日活动总结
2015/03/24 职场文书
小学语文课《掌声》教学反思
2016/03/03 职场文书
小程序教您怎样你零成本推广获取数万用户的方法
2019/07/30 职场文书
vue使用echarts实现折线图
2022/03/21 Vue.js