python里 super类的工作原理详解


Posted in Python onJune 19, 2019

super 的工作原理如下:

def super(cls, inst):
  mro = inst.__class__.mro()
  return mro[mro.index(cls) + 1]

其中,cls 代表类,inst 代表实例,上面的代码做了两件事:

  1. 获取 inst 的 MRO 列表
  2. 查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类,即 mro[index + 1]

当你使用 super(cls, inst) 时,Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类。

下面看一个例子:

class A:
  def __init__(self):
    self.n = 2

  def add(self, m):
    print('\n\nself is {0} @A.add'.format(self))
    self.n += m


class B(A):
  def __init__(self):
    self.n = 3

  def add(self, m):
    print('\n\nself is {0} @B.add'.format(self))
    super(B, self).add(m)
    self.n += 3


class C(A):
  def __init__(self):
    self.n = 4

  def add(self, m):
    print('\n\nself is {0} @C.add'.format(self))
    super(C, self).add(m)
    self.n += 4


class D(B, C):
  def __init__(self):
    self.n = 5

  def add(self, m):
    print('\n\nself is {0} @D.add'.format(self))

    print(super(D, self).__self__)
    print(super(D, self).__thisclass__)

    super(D, self).add(m)
    self.n += 5


if __name__ == '__main__':

  print(D.mro())
  d = D()
  d.add(2) # 等于是: D.add(d, 2)
  print(d.n)

结果是:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

<__main__.D object at 0x101ef16d8>


self is <__main__.D object at 0x101ef16d8> @D.add
<__main__.D object at 0x101ef16d8>
<class '__main__.D'>


self is <__main__.D object at 0x101ef16d8> @B.add


self is <__main__.D object at 0x101ef16d8> @C.add


self is <__main__.D object at 0x101ef16d8> @A.add
19

来通过这个结果具体说几点细节:

print(D.mro()) 首先打印出 D类的 mro 列表:[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 。 这个非常好理解。

然后我们通过d = D()创建一个D类的实例: <__main__.D object at 0x101ef16d8>; 为了方便, 我们就把这个实例object at 0x101ef16d8 叫做 “小明” 吧

召唤d.add(2) 这个函数的时候,D类中add函数的self实际上就是这个刚被创建的小明同学object at 0x101ef16d8.

那么接下来呢,super(D, self) 就是在 object at 0x101ef16d8 的mro列表中,在小明的MRO列表中, 找到 class D(D类)的下一个 class(类), 这里也就是 class B (B类) 。

注意 mro列表里 <class '__main__.D'> 的下一个是 <class '__main__.B'>

每一个 add 函数打印的都是 self is <__main__.D object at 0x101ef16d8>, 往上追溯的过程中,无论到了哪一级,self始终都是最初创建的那个 D类的实例。

这是为什么呢?

注意看 print(super(D, self).__self__) 那一行返还的输出:<__main__.D object at 0x101ef16d8> .

哦哦?! 这他妈的不是小明吗?

也就是说, super()虽然找到的是B类,召唤的是B类的 add()函数,但它的self仍然是最开始创建的D类实例(我们的 小明同学),而且召唤add()这个函数时,仍然是把这样的一个self传给了 class B 的 add()函数。

我们的 “小明”, 就这样被一次次的往上传导到了每一级的 add() 函数中, 于是每一级打印的都是:

self is <__main__.D object at 0x101ef16d8> 或者说: self is 小明

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

Python 相关文章推荐
python self,cls,decorator的理解
Jul 13 Python
urllib2自定义opener详解
Feb 07 Python
Python fileinput模块使用实例
May 28 Python
python中如何正确使用正则表达式的详细模式(Verbose mode expression)
Nov 08 Python
Python数据分析之双色球中蓝红球分析统计示例
Feb 03 Python
pandas Dataframe行列读取的实例
Jun 08 Python
使用pandas把某一列的字符值转换为数字的实例
Jan 29 Python
python3 图片 4通道转成3通道 1通道转成3通道 图片压缩实例
Dec 03 Python
Python连接Mysql进行增删改查的示例代码
Aug 03 Python
python 基于opencv 实现一个鼠标绘图小程序
Dec 11 Python
如何用python识别滑块验证码中的缺口
Apr 01 Python
Python+Selenium实现读取网易邮箱验证码
Mar 13 Python
Python创建或生成列表的操作方法
Jun 19 #Python
Django REST framework 分页的实现代码
Jun 19 #Python
python获取磁盘号下盘符步骤详解
Jun 19 #Python
对PyQt5基本窗口控件 QMainWindow的使用详解
Jun 19 #Python
PyQt5 多窗口连接实例
Jun 19 #Python
django框架实现一次性上传多个文件功能示例【批量上传】
Jun 19 #Python
pyqt5对用qt designer设计的窗体实现弹出子窗口的示例
Jun 19 #Python
You might like
递归列出所有文件和目录
2006/10/09 PHP
使用PHP的日期与时间函数技巧
2008/04/24 PHP
发一个php简单的伪原创程序,配合商城采集用的
2010/10/12 PHP
Thinkphp实现MySQL读写分离操作示例
2014/06/25 PHP
php数字运算验证码的实现代码
2015/07/30 PHP
php实现通过stomp协议连接ActiveMQ操作示例
2020/02/23 PHP
学习ExtJS TextField常用方法
2009/10/07 Javascript
Jquery网页出现的乱码问题的三种解决方法
2013/06/30 Javascript
jQuery插件实现大图全屏图片相册
2015/03/14 Javascript
如何改进javascript代码的性能
2015/04/02 Javascript
微信小程序 视图层(xx.xml)和逻辑层(xx.js)详细介绍
2016/10/13 Javascript
用JavaScript实现让浏览器停止载入页面的方法
2017/01/19 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
2017/04/18 Javascript
vue实现文章内容过长点击阅读全文功能的实例
2017/12/28 Javascript
jQuery+CSS实现的table表格行列转置功能示例
2018/01/08 jQuery
Vue使用vue-area-linkage实现地址三级联动效果的示例
2018/06/27 Javascript
layer.alert自定义关闭回调事件的方法
2019/09/27 Javascript
基于form-data请求格式详解
2019/10/29 Javascript
vue实现淘宝购物车功能
2020/04/20 Javascript
在vue中created、mounted等方法使用小结
2020/07/21 Javascript
python求众数问题实例
2014/09/26 Python
python实现隐马尔科夫模型HMM
2018/03/25 Python
pytorch 调整某一维度数据顺序的方法
2018/12/08 Python
python自定义函数实现一个数的三次方计算方法
2019/01/20 Python
python使用Paramiko模块实现远程文件拷贝
2019/04/30 Python
python关于矩阵重复赋值覆盖问题的解决方法
2019/07/19 Python
Python合并2个字典成1个新字典的方法(9种)
2019/12/19 Python
澳大利亚领先的在线葡萄酒零售商:Get Wines Direct
2018/03/27 全球购物
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
英国优质家居用品网上品牌:URBANARA
2018/06/01 全球购物
英文版餐饮业求职信
2013/10/18 职场文书
中学生操行评语大全
2014/04/24 职场文书
2014年创先争优活动总结
2014/05/04 职场文书
党员承诺书格式范文
2015/04/28 职场文书
2016年母亲节广告语
2016/01/28 职场文书
如何让你的Nginx支持分布式追踪详解
2022/07/07 Servers