一、问题的发现与提出

在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1:

代码段1:

class A:

def __init__(self):

print "enter A"

print "leave A"

class B(A):

def __init__(self):

print "enter B"

A.__init__(self)

print "leave B"

>>> b = B()

enter B

enter A

leave A

leave B

即,使用非绑定的类方法(用类名来引用的方法),并在参数列表中,引入待绑定的对象(self),从而达到调用父类的目的。

这样做的缺点是,当一个子类的父类发生变化时(如类B的父类由A变为C时),必须遍历整个类定义,把所有的通过非绑定的方法的类名全部替换过来,例如代码段2,

代码段2:

class B(C): # A --> C

def __init__(self):

print "enter B"

C.__init__(self) # A --> C

print "leave B"

如果代码简单,这样的改动或许还可以接受。但如果代码量庞大,这样的修改可能是灾难性的。

因此,自Python 2.2开始,Python添加了一个关键字super,来解决这个问题。下面是Python 2.3的官方文档说明:

super(type[, object-or-type])

Return the superclass of type. If the second argument is omitted the super object

returned is unbound. If the second argument is an object, isinstance(obj, type)

must be true. If the second argument is a type, issubclass(type2, type) must be

true. super() only works for new-style classes.

A typical use for calling a cooperative superclass method is:

class C(B):

def meth(self, arg):

super(C, self).meth(arg)

New in version 2.2.

从说明来看,可以把类B改写如代码段3:

代码段3:

class A(object): # A must be new-style class

def __init__(self):

print "enter A"

print "leave A"

class B(C): # A --> C

def __init__(self):

print "enter B"

super(B, self).__init__()

print "leave B"

尝试执行上面同样的代码,结果一致,但修改的代码只有一处,把代码的维护量降到最低,是一个不错的用法。因此在我们的开发过程中,super关键字被大量使用,而且一直表现良好。

在我们的印象中,对于super(B, self).__init__()是这样理解的:super(B, self)首先找到B的父类(就是类A),然后把类B的对象self转换为类A的对象(通过某种方式,一直没有考究是什么方式,惭愧),然后“被转换”的类A对象调用自己的__init__函数。考虑到super中只有指明子类的机制,因此,在多继承的类定义中,通常我们保留使用类似代码段1的方法。

有一天某同事设计了一个相对复杂的类体系结构(我们先不要管这个类体系设计得是否合理,仅把这个例子作为一个题目来研究就好),代码如代码段4:

代码段4:

class A(object):

def __init__(self):

print "enter A"

print "leave A"

class B(object):

def __init__(self):

print "enter B"

print "leave B"

class C(A):

def __init__(self):

print "enter C"

super(C, self).__init__()

print "leave C"

class D(A):

def __init__(self):

print "enter D"

super(D, self).__init__()

print "leave D"

class E(B, C):

def __init__(self):

print "enter E"

B.__init__(self)

C.__init__(self)

print "leave E"

class F(E, D):

def __init__(self):

print "enter F"

E.__init__(self)

D.__init__(self)

print "leave F"

>>> f = F()

enter F

enter E

enter B

leave B

enter C

enter D

enter A

leave A

leave D

leave C

leave E

enter D

enter A

leave A

leave D

leave F

明显地,类A和类D的初始化函数被重复调用了2次,这并不是我们所期望的结果!我们所期望的结果是最多只有类A的初始化函数被调用2次——其实这是多继承的类体系必须面对的问题。我们把代码段4的类体系画出来,如下图:

object

| /

| A

| / |

B C D

/ / |

E |

/ |

F

按我们对super的理解,从图中可以看出,在调用类C的初始化函数时,应该是调用类A的初始化函数,但事实上却调用了类D的初始化函数。好一个诡异的问题!

详情请点击:Python中的super用法详解_python_脚本之家​www.jb51.net

注意点:

1.__init__是析构函数,也就是类被实例化(生成对象)之后默认加载的内容,常用于初始化类。

2.__init__是函数只加在一次,且在类运行时首先运行。

3.#通过super初始化父类,__init__()函数无self,若直接QtWidgets.QWidget.__init__(self),括号里是有self的

python中的super用法详解_【Python】【类】super用法详解相关推荐

  1. python中from import*的*什么意思_[Python]Python中的import和from import

    在python用import或者from...import来导入相应的模块. 模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序 ...

  2. python中字符串类型的encode()方法_第五章 Python字符串常用方法详解

    5.1 Python字符串拼接(包含字符串拼接数字) 在 Python中拼接(连接)字符串很简单,可以直接将两个字符串紧挨着写在一起,具体格式为: strname = "str1" ...

  3. 站长在线Python精讲:在Python中使用split()方法分割、使用join()方法合并字符串详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python中使用split()方法分割.使用join()方法合并字符串详解>.本知识点主要内容有:在Python中使用s ...

  4. python中continue用法案例_记录今天学习python中for与while循环针对break和continue的用法...

    python中有两个主要的循环for与while,其中针对这两个循环有两种不同的中断用法break与continue. 首先先看下面的循环代码: 1: for i in range(10):#变量i带 ...

  5. python中的数据分析库有哪些_全网最全数据分析师干货-python篇

    作者:胖熊酱 著作权归作者所有.AI开发者获得授权转载,禁止二次转载 https://zhuanlan.zhihu.com/p/79873148 注:封面图片来自网络 最近正在准备面试,故整理了很多面 ...

  6. 创建二维数组 以及 python中[0 ]* n与[0 for _ in range(n)]的区别与联系

    一.浅拷贝于深拷贝 关于浅拷贝于深拷贝:Python 的深拷贝和浅拷贝 直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy) ...

  7. python中意外缩进是什么意思_语法错误 - 如何处理python中的“意外缩进”?

    语法错误 - 如何处理python中的"意外缩进"? 如何纠正python中的"意外缩进"错误? 15个解决方案 116 votes Python在行的开头使用 ...

  8. python中字符型用什么表示_「小白学Python」Python中最常用的数据类型:字符串

    Python中有6个标准数据类型,分别是:Number(数值).String(字符串).List(列表).Tuple(元组).Sets(集合).Dictionary(字典). 其中,String(字符 ...

  9. python中函数和方法的区别?Python编程判断当前获取的对象是函数还是方法

    python中函数和方法的区别?Python编程判断当前获取的对象是函数还是方法 目录

  10. Python中的图像处理(第九章)Python图像增强

    Python中的图像处理(第九章)Python图像增强 前言 一. Python准备 二. Python仿真 三. 小结 前言 随着人工智能研究的不断兴起,Python的应用也在不断上升,由于Pyth ...

最新文章

  1. 查询语句索引不能使用的一些情况
  2. Java堆和栈的一些区别。。。
  3. The Internals of PostgreSQL
  4. 【常用技巧】标准模板库(STL)
  5. Node.js 入门详解(四)
  6. Windows7 Xp Mode部署与讲解
  7. vue去掉#——History模式
  8. Python 这么简单还用学吗?
  9. vmware16安装mac虚拟机的unlocker
  10. 如何用Word打开PDF文件?
  11. JS点击按钮复制文本
  12. python+nodejs+vue大学生心理健康测评管理系统
  13. 服务器网站被cc攻击,网站被CC攻击怎么办?宝塔防火墙防CC设置详解
  14. HashMap非线程安全问题
  15. 饭后Android 第二餐-复选框CheckBox+开关按钮Switch+单选按钮RadioButton
  16. HTML网页表格标签,HTML静态网页(标签、表格)
  17. Linux系统架构概述
  18. halcon改变图像大小
  19. Linux如何更改root用户密码
  20. 匿名管道和命名管道(代码剖析)

热门文章

  1. guid主分区表损坏怎么办_轻钢龙骨隔墙怎么办?轻钢龙骨隔墙的做法
  2. java:1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
  3. java文件下载并添加水印_Java下载文件加文字水印(Excel、PDF、图片)
  4. 多个ip对应的是同一个mac_Python3+Scapy安装使用 + 查询本机对应网卡,IP,MAC代码...
  5. 网页html好学嘛,javascript好学么?
  6. 单词背诵【CodeVS3013】 哈希
  7. JS判断上传文件类型
  8. [CQOI2012]交换棋子【网络流】【费用流】
  9. mysql 自定义函数
  10. 习惯的力量之五让迟延见鬼去吧