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 相关文章推荐
通过数据库向Django模型添加字段的示例
Jul 21 Python
Python 中的 else详解
Apr 23 Python
Python实现抓取网页生成Excel文件的方法示例
Aug 05 Python
python 常用的基础函数
Jul 10 Python
用python统计代码行的示例(包括空行和注释)
Jul 24 Python
python编程使用协程并发的优缺点
Sep 20 Python
解决win7操作系统Python3.7.1安装后启动提示缺少.dll文件问题
Jul 15 Python
如何将 awk 脚本移植到 Python
Dec 09 Python
tensorflow之并行读入数据详解
Feb 05 Python
Python如何获取文件路径/目录
Sep 22 Python
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
Apr 14 Python
Python使用pandas导入csv文件内容的示例代码
Dec 24 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
php checkdate、getdate等日期时间函数操作详解
2010/03/11 PHP
PHP 获取远程网页内容的代码(fopen,curl已测)
2011/06/06 PHP
PHP 第二节 数据类型之数值型
2012/04/28 PHP
Nigma vs Alliance BO5 第一场2.14
2021/03/10 DOTA
javascript OFFICE控件测试代码
2009/12/08 Javascript
JQuery1.4+ Ajax IE8 内存泄漏问题
2010/10/15 Javascript
web的各种前端打印方法之jquery打印插件jqprint实现网页打印
2013/01/09 Javascript
JQuery实现表格中相同单元格合并示例代码
2013/06/26 Javascript
Jquery通过JSON字符串创建JSON对象
2014/08/24 Javascript
HTML5+setCutomValidity()函数验证表单实例分享
2015/04/24 Javascript
node文件批量重命名的方法示例
2017/10/23 Javascript
webpack4 SCSS提取和懒加载的示例
2018/09/03 Javascript
Vue2 添加数据可视化支持的方法步骤
2019/01/02 Javascript
微信小程序的授权实现过程解析
2019/08/02 Javascript
详解JavaScript 事件流
2020/09/02 Javascript
HTML中使用python屏蔽一些基本功能的方法
2017/07/07 Python
flask + pymysql操作Mysql数据库的实例
2017/11/13 Python
python 定义n个变量方法 (变量声明自动化)
2018/11/10 Python
浅谈Tensorflow 动态双向RNN的输出问题
2020/01/20 Python
TensorFlow实现自定义Op方式
2020/02/04 Python
Python实现自动打开电脑应用的示例代码
2020/04/17 Python
常用的10个Python实用小技巧
2020/08/10 Python
python如何停止递归
2020/09/09 Python
为智能设备设计个性化保护套网站:caseable
2017/01/05 全球购物
Sofmap官网:日本著名的数码电器专卖店
2017/05/19 全球购物
Boden英国官网:英国知名原创时装品牌
2018/11/06 全球购物
Perfume’s Club意大利官网:欧洲美妆电商
2019/05/03 全球购物
Java多态性的定义以及类型
2014/09/16 面试题
如何利用cmp命令比较文件
2013/09/23 面试题
公务员更新知识培训实施方案
2014/03/31 职场文书
二手房买卖协议书
2014/04/10 职场文书
股指期货心得体会
2014/09/13 职场文书
婚宴邀请函
2015/01/30 职场文书
写作技巧:优秀文案必备的3种结构
2019/08/19 职场文书
jQuery class属性操作addClass()与removeClass()、hasClass()、toggleClass()
2021/03/31 jQuery
详解Python中下划线的5种含义
2021/07/15 Python