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生成器表达式和列表解析
Mar 10 Python
Python Flask基础教程示例代码
Feb 07 Python
Django安装配置mysql的方法步骤
Oct 15 Python
Python中logging.NullHandler 的使用教程
Nov 29 Python
pyinstaller参数介绍以及总结详解
Jul 12 Python
python opencv将表格图片按照表格框线分割和识别
Oct 30 Python
python实发邮件实例详解
Nov 11 Python
六种酷炫Python运行进度条效果的实现代码
Jul 17 Python
python mock测试的示例
Oct 19 Python
python绘图模块之利用turtle画图
Feb 12 Python
Python 使用dict实现switch的操作
Apr 07 Python
Python实现查询剪贴板自动匹配信息的思路详解
Jul 09 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网站备份程序代码分享
2011/06/10 PHP
PHP之密码加密的几种方式
2015/07/29 PHP
phpinfo()中Loaded Configuration File(none)的解决方法
2017/01/16 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
2018/06/06 PHP
ASP中进行HTML数据及JS数据编码函数
2009/11/11 Javascript
jQuery.validate 常用方法及需要注意的问题
2013/03/20 Javascript
javascript的解析执行顺序在各个浏览器中的不同
2014/03/17 Javascript
利用jQuery实现可以编辑的表格
2014/05/26 Javascript
JavaScript中创建对象的模式汇总
2016/04/19 Javascript
一步步教你利用Canvas对图片进行处理
2017/09/19 Javascript
详解基于vue-cli优化的webpack配置
2017/11/06 Javascript
微信小程序如何获取用户收货地址
2018/11/27 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
vue-next/runtime-core 源码阅读指南详解
2019/10/25 Javascript
JavaScript中window和document用法详解
2020/07/28 Javascript
[00:27]DOTA2荣耀之路2:Patience from zhou!
2018/05/24 DOTA
[04:59]DOTA2-DPC中国联赛 正赛 Ehome vs iG 选手采访
2021/03/11 DOTA
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
python中使用xlrd、xlwt操作excel表格详解
2015/01/29 Python
使用beaker让Facebook的Bottle框架支持session功能
2015/04/23 Python
在Django框架中编写Contact表单的教程
2015/07/17 Python
Python中time模块与datetime模块在使用中的不同之处
2015/11/24 Python
Python金融数据可视化汇总
2017/11/17 Python
python读取csv文件并把文件放入一个list中的实例讲解
2018/04/27 Python
对pyqt5多线程正确的开启姿势详解
2019/06/14 Python
PyTorch 对应点相乘、矩阵相乘实例
2019/12/27 Python
python3 中使用urllib问题以及urllib详解
2020/08/03 Python
美国领先的在线邮轮旅游公司:CruiseDirect
2018/06/07 全球购物
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
Hotels.com泰国:酒店预订网站
2019/11/20 全球购物
最新党员的自我评价分享
2013/11/04 职场文书
写演讲稿要注意的六件事
2014/01/14 职场文书
法人单位适用的授权委托书
2014/09/19 职场文书
2014年女职工工作总结
2014/11/27 职场文书
Python Pandas常用函数方法总结
2021/06/15 Python
Springboot集成阿里云OSS上传文件系统教程
2021/06/28 Java/Android