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连接oracle数据库实例
Oct 17 Python
python中Genarator函数用法分析
Apr 08 Python
使用Python装饰器在Django框架下去除冗余代码的教程
Apr 16 Python
Python中内置数据类型list,tuple,dict,set的区别和用法
Dec 14 Python
Python中的默认参数实例分析
Jan 29 Python
python使用Tkinter实现在线音乐播放器
Jan 30 Python
详解python多线程、锁、event事件机制的简单使用
Apr 27 Python
在Python运行时动态查看进程内部信息的方法
Feb 22 Python
对python中的*args与**kwgs的含义与作用详解
Aug 28 Python
tensorflow实现将ckpt转pb文件的方法
Apr 22 Python
Python必须了解的35个关键词
Jul 16 Python
python代数式括号有效性检验示例代码
Oct 04 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下一个阿拉伯数字转中文数字的函数
2007/07/16 PHP
PHP 截取字符串 分别适合GB2312和UTF8编码情况
2009/02/12 PHP
PHP生成随机用户名和密码的实现代码
2013/02/27 PHP
PHP怎么实现网站保存快捷方式方便用户随时浏览
2013/08/15 PHP
PHP超全局变量实现原理及代码解析
2020/09/01 PHP
JS控制图片翻转示例代码(兼容firefox,ie,chrome)
2013/12/19 Javascript
JavaScript实现动态删除列表框值的方法
2015/08/12 Javascript
jquery动感漂浮导航菜单代码分享
2020/04/15 Javascript
理解JavaScript中Promise的使用
2016/01/18 Javascript
基于jQuery制作小图标上下滑动特效
2017/01/18 Javascript
vue v-on监听事件详解
2017/05/17 Javascript
Require.js的基本用法详解
2017/07/03 Javascript
vue-cli2打包前和打包后的css前缀不一致的问题解决
2018/08/24 Javascript
JS原型与继承操作示例
2019/05/09 Javascript
vue实现动态按钮功能
2019/05/13 Javascript
javascript实现遮罩层动态效果实例
2019/05/14 Javascript
js实现小星星游戏
2020/03/23 Javascript
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
使用python读取txt文件的内容,并删除重复的行数方法
2018/04/18 Python
Python 绘图库 Matplotlib 入门教程
2018/04/19 Python
下载python中Crypto库报错:ModuleNotFoundError: No module named ‘Crypto’的解决
2018/04/23 Python
Python实现高斯函数的三维显示方法
2018/12/29 Python
运用Python的webbrowser实现定时打开特定网页
2019/02/21 Python
24式加速你的Python(小结)
2019/06/13 Python
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
乌克兰鞋类购物网站:Eobuv.com.ua
2020/11/28 全球购物
2019史上最全Database工程师题库
2015/12/06 面试题
竞选卫生委员演讲稿
2014/04/28 职场文书
金融保险专业求职信
2014/09/03 职场文书
2014年班干部工作总结
2014/11/25 职场文书
2014年居委会工作总结
2014/12/09 职场文书
小学教师先进事迹材料
2014/12/15 职场文书
计划生育目标责任书
2015/05/09 职场文书
PyQt5结合QtDesigner实现文本框读写操作
2021/06/11 Python
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
人物搭配车车超萌联名预备中 【咒术迴战】 ⨯ 【天竺鼠车车】 展开合作
2022/04/11 日漫