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内存管理分析
Apr 08 Python
Python随机生成数据后插入到PostgreSQL
Jul 28 Python
使用pyecharts无法import Bar的解决方案
Apr 23 Python
Python 错误和异常代码详解
Jan 29 Python
Python实现扣除个人税后的工资计算器示例
Mar 26 Python
tensorflow实现加载mnist数据集
Sep 08 Python
python替换字符串中的子串图文步骤
Jun 19 Python
简单的Python调度器Schedule详解
Aug 30 Python
pyqt5中动画的使用详解
Apr 01 Python
PyTorch中的C++扩展实现
Apr 02 Python
python软件测试Jmeter性能测试JDBC Request(结合数据库)的使用详解
Jan 26 Python
python爬取豆瓣电影TOP250数据
May 23 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中通过语义URL防止网站被攻击的方法分享
2011/09/08 PHP
我整理的PHP 7.0主要新特性
2016/01/07 PHP
PHP实现统计所有字符在字符串中出现次数的方法
2017/10/17 PHP
Firebug 字幕文件JSON地址获取代码
2009/10/28 Javascript
Javascript 解疑
2009/11/11 Javascript
两个JavaScript jsFiddle JSBin在线调试器
2010/03/14 Javascript
ExtJS 设置级联菜单的默认值
2010/06/13 Javascript
JS获取各种宽度、高度的简单介绍
2014/12/19 Javascript
JavaScript中document对象使用详解
2015/01/06 Javascript
基于jQuery实现文本框只能输入数字(小数、整数)
2016/01/14 Javascript
jQuery实现立体式数字滚动条增加效果
2016/12/21 Javascript
jQuery自定义图片上传插件实例代码
2017/04/04 jQuery
angular+webpack2实战例子
2017/05/23 Javascript
jQuery Position方法使用和兼容性
2017/08/23 jQuery
快速解决brew安装特定版本flow的问题
2018/05/17 Javascript
node错误处理与日志记录的实现
2018/12/24 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
python判断windows隐藏文件的方法
2014/03/21 Python
fastcgi文件读取漏洞之python扫描脚本
2017/04/23 Python
Python使用numpy实现BP神经网络
2018/03/10 Python
python爬虫之模拟登陆csdn的实例代码
2018/05/18 Python
Python hashlib模块用法实例分析
2018/06/12 Python
Python爬虫实现抓取京东店铺信息及下载图片功能示例
2018/08/07 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
python连接打印机实现打印文档、图片、pdf文件等功能
2020/02/07 Python
pyspark给dataframe增加新的一列的实现示例
2020/04/24 Python
Python Dict找出value大于某值或key大于某值的所有项方式
2020/06/05 Python
浅谈python处理json和redis hash的坑
2020/07/16 Python
好学生评语大全
2014/05/05 职场文书
社区综治宣传月活动总结
2014/07/02 职场文书
新闻专业毕业生求职信
2014/08/08 职场文书
公司离职证明标准样本
2014/10/05 职场文书
兼职安全员岗位职责
2015/02/15 职场文书
党员干部廉洁自律承诺书
2015/04/28 职场文书
高中化学教学反思
2016/02/22 职场文书
Redis官方可视化工具RedisInsight安装使用教程
2022/04/19 Redis