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 相关文章推荐
下载给定网页上图片的方法
Feb 18 Python
在Python中使用NLTK库实现对词干的提取的教程
Apr 08 Python
python图像处理之镜像实现方法
May 30 Python
Python pass详细介绍及实例代码
Nov 24 Python
python3调用百度翻译API实现实时翻译
Aug 16 Python
利用python实现短信和电话提醒功能的例子
Aug 08 Python
浅析PEP570新语法: 只接受位置参数
Oct 15 Python
使用OpenCV对车道进行实时检测的实现示例代码
Jun 19 Python
python interpolate插值实例
Jul 06 Python
Python extract及contains方法代码实例
Sep 11 Python
matplotlib设置颜色、标记、线条,让你的图像更加丰富(推荐)
Sep 25 Python
python实现商品进销存管理系统
May 30 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
PHP5 的对象赋值机制介绍
2011/08/02 PHP
PHP向浏览器输出内容的4个函数总结
2014/11/17 PHP
laravel学习教程之存取器
2016/07/30 PHP
用javascript做拖动布局的思路
2008/05/31 Javascript
一个JQuery写的点击上下滚动的小例子
2011/08/27 Javascript
JS+css 图片自动缩放自适应大小
2013/08/08 Javascript
JavaScript生成GUID的多种算法小结
2013/08/18 Javascript
JQuery中DOM事件冒泡实例分析
2015/06/13 Javascript
javascript伸缩菜单栏实现代码分享
2015/11/12 Javascript
Jquery Mobile 自定义按钮图标
2015/11/18 Javascript
基于jQuery实现发送短信验证码后的倒计时功能(无视页面关闭)
2016/09/02 Javascript
JavaScript cookie详解及简单实例应用
2016/12/31 Javascript
微信小程序中使用javascript 回调函数
2017/05/11 Javascript
详解vue-cli脚手架build目录中的dev-server.js配置文件
2017/11/24 Javascript
12条写出高质量JS代码的方法
2018/01/07 Javascript
解决vue中对象属性改变视图不更新的问题
2018/02/23 Javascript
KnockoutJS数组比较算法实例详解
2019/11/25 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
2020/03/25 Javascript
python使用nntp读取新闻组内容的方法
2015/05/08 Python
JPype实现在python中调用JAVA的实例
2017/07/19 Python
python 日期操作类代码
2018/05/05 Python
python+opencv+caffe+摄像头做目标检测的实例代码
2018/08/03 Python
Python Django框架url反向解析实现动态生成对应的url链接示例
2019/10/18 Python
基于python3抓取pinpoint应用信息入库
2020/01/08 Python
如何利用Python matplotlib绘制雷达图
2020/12/21 Python
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
购买英国原创艺术:Art Gallery
2018/08/25 全球购物
娱乐地球:Entertainment Earth
2020/01/08 全球购物
学生实习自我鉴定
2013/10/11 职场文书
金融专业毕业生推荐信
2013/11/26 职场文书
微型企业创业投资计划书
2014/01/10 职场文书
竞选班长的演讲稿
2014/04/24 职场文书
2014优秀大学生简历自我评价
2014/09/15 职场文书
2014企业年终工作总结
2014/12/23 职场文书
创业计划书之服装
2019/10/07 职场文书
go使用Gin框架利用阿里云实现短信验证码功能
2021/08/04 Golang