Python3里的super()和__class__使用介绍


Posted in Python onApril 23, 2015

子类里访问父类的同名属性,而又不想直接引用父类的名字,因为说不定什么时候会去修改它,所以数据还是只保留一份的好。其实呢,还有更好的理由不去直接引用父类的名字,参见 Python's super() considered super! | Deep Thoughts by Raymond Hettinger。

这时候就该 super() 登场啦——

class A:

  def m(self):

    print('A')
class B(A):

  def m(self):

    print('B')

    super().m()
B().m()

当然 Python 2 里 super() 是一定要参数的,所以得这么写:
class B(A):

  def m(self):

    print('B')

    super(B, self).m()

需要提到自己的名字。这个名字也是动态查找的,在这种情况下替换第三方库中的类会出问题。

super() 很好地解决了访问父类中的方法的问题。那么,如果要访问父类的父类(准确地说,是方法解析顺序(MRO)中位于第三的类)的属性呢?

比如,B 类是继承 A 的,它重写了 A 的 m 方法。现在我们需要一个 C 类,它需要 B 类的一些方法,但是不要 B 的 m 方法,而改用 A 的。怎么间接地引用到 A 的 m 方法呢?使用self.__class__肯定是不行的,因为 C 还可能被进一步继承。

从文档中我注意到,super 的实现是通过插入一个名为 __class__ 的名字来实现的(super 会从调用栈里去查找这个 __class__ 名字)。所以,就像文档里暗示的,其实可以直接在定义方法时访问 __class__ 名字,它总是该方法被定义的类。继续我们的单字母类:

class C(B):

  def m(self):

    print('C')

    # see the difference!

    print(__class__.__mro__)

    print(self.__class__.__mro__)

    __class__.__mro__[2].m(self)
class D(C):

  def m(self):

    print('D')

    super().m()
o = D()

o.m()

会得到:
D

C

(<class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)

(<class 't.D'>, <class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)

A

不过,PyPy 并不支持这个 __class__ 名字。
Python 相关文章推荐
深入浅析Python字符编码
Nov 12 Python
详解Python各大聊天系统的屏蔽脏话功能原理
Dec 01 Python
matplotlib简介,安装和简单实例代码
Dec 26 Python
matplotlib绘图实例演示标记路径
Jan 23 Python
python去除文件中重复的行实例
Jun 29 Python
python中单例常用的几种实现方法总结
Oct 13 Python
实例讲解Python中浮点型的基本内容
Feb 11 Python
python opencv 图像拼接的实现方法
Jun 27 Python
python numpy 矩阵堆叠实例
Jan 17 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
Feb 03 Python
使用keras实现BiLSTM+CNN+CRF文字标记NER
Jun 29 Python
JAVA SpringMVC实现自定义拦截器
Mar 16 Python
Python实现的飞速中文网小说下载脚本
Apr 23 #Python
Python中使用PyQt把网页转换成PDF操作代码实例
Apr 23 #Python
Python里disconnect UDP套接字的方法
Apr 23 #Python
Python实现的Google IP 可用性检测脚本
Apr 23 #Python
Python3.2中的字符串函数学习总结
Apr 23 #Python
Python与Redis的连接教程
Apr 22 #Python
Python实现的数据结构与算法之快速排序详解
Apr 22 #Python
You might like
提升PHP速度全攻略
2006/10/09 PHP
php生成随机密码的三种方法小结
2010/09/04 PHP
PHP面向对象程序设计重载(overloading)操作详解
2019/06/13 PHP
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
在javascript将NodeList作为Array数组处理的方法
2010/07/09 Javascript
文字溢出实现溢出的部分再放入一个新生成的div中具体代码
2013/05/17 Javascript
setInterval与clearInterval的使用示例代码
2014/01/28 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
JS实现仿google、百度搜索框输入信息智能提示的实现方法
2015/04/20 Javascript
jquery实现的伪分页效果代码
2015/10/29 Javascript
jQuery Easyui datagrid行内实现【添加】、【编辑】、【上移】、【下移】
2016/12/19 Javascript
微信小程序实现给循环列表添加点击样式实例
2017/04/26 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
Vue-router的使用和出现空白页,路由对象属性详解
2018/09/03 Javascript
原生JS实现旋转轮播图+文字内容切换效果【附源码】
2018/09/29 Javascript
python异步任务队列示例
2014/04/01 Python
python编写简单爬虫资料汇总
2016/03/22 Python
在python image 中安装中文字体的实现方法
2019/08/22 Python
解决python多行注释引发缩进错误的问题
2019/08/23 Python
python能做什么 python的含义
2019/10/12 Python
基于python获取本地时间并转换时间戳和日期格式
2020/10/27 Python
css3 利用transform打造走动的2D时钟
2020/10/20 HTML / CSS
会计专业毕业生自我评价
2013/09/25 职场文书
拓展培训心得体会
2014/01/04 职场文书
2014年幼儿园教师工作总结
2014/11/08 职场文书
新教师个人工作总结
2015/02/06 职场文书
会计简历自我评价
2015/03/10 职场文书
手机销售员岗位职责
2015/04/11 职场文书
行政介绍信范文
2015/05/04 职场文书
装修安全责任协议书
2016/03/22 职场文书
导游词之塘栖古镇
2019/12/04 职场文书
Python使用Kubernetes API访问集群
2021/05/30 Python
SSM项目使用拦截器实现登录验证功能
2022/01/22 Java/Android
《雀魂PONG☆》4月1日播出 PV角色设定情报
2022/03/20 日漫
Netty分布式客户端接入流程初始化源码分析
2022/03/25 Java/Android
golang操作rocketmq的示例代码
2022/04/06 Golang