原文地址:https://www.zhihu.com/question/20040039

针对你的问题,答案是可以,并没有区别。但是这题下的回答我感觉都不够好。

要谈论 super,首先我们应该无视 "super" 这个名字带给我们的干扰。

不要一说到 super 就想到父类!super 指的是 MRO 中的下一个类!
不要一说到 super 就想到父类!super 指的是 MRO 中的下一个类!
不要一说到 super 就想到父类!super 指的是 MRO 中的下一个类!

一说到 super 就想到父类这是初学者很容易犯的一个错误,也是我当年犯的错误。
忘记了这件事之后,再去看这篇文章:Python’s super() considered super!
这是 Raymond Hettinger 写的一篇文章,也是全世界公认的对 super 讲解最透彻的一篇文章,凡是讨论 super 都一定会提到它(当然还有一篇 Python's Super Considered Harmful)。

如果不想看长篇大论就去看这个答案,super 其实干的是这件事:

def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]

两个参数 cls 和 inst 分别做了两件事:
1. inst 负责生成 MRO 的 list
2. 通过 cls 定位当前 MRO 中的 index, 并返回 mro[index + 1]
这两件事才是 super 的实质,一定要记住!
MRO 全称 Method Resolution Order,它代表了类继承的顺序。后面详细说。

举个例子

class Root(object):
def __init__(self):
print("this is Root") class B(Root):
def __init__(self):
print("enter B")
# print(self) # this will print <__main__.D object at 0x...>
super(B, self).__init__()
print("leave B") class C(Root):
def __init__(self):
print("enter C")
super(C, self).__init__()
print("leave C") class D(B, C):
pass d = D()
print(d.__class__.__mro__)

输出

enter B
enter C
this is Root
leave C
leave B
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Root'>, <type 'object'>)

知道了 super 和父类其实没有实质关联之后,我们就不难理解为什么 enter B 下一句是 enter C 而不是 this is Root(如果认为 super 代表“调用父类的方法”,会想当然的认为下一句应该是this is Root)。流程如下,在 B 的 __init__ 函数中:

super(B, self).__init__()

首先,我们获取 self.__class__.__mro__,注意这里的 self 是 D 的 instance 而不是 B 的

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Root'>, <type 'object'>)

然后,通过 B 来定位 MRO 中的 index,并找到下一个。显然 B 的下一个是 C。于是,我们调用 C 的 __init__,打出 enter C。

顺便说一句为什么 B 的 __init__ 会被调用:因为 D 没有定义 __init__,所以会在 MRO 中找下一个类,去查看它有没有定义 __init__,也就是去调用 B 的 __init__。

其实这一切逻辑还是很清晰的,关键是理解 super 到底做了什么。

于是,MRO 中类的顺序到底是怎么排的呢?Python’s super() considered super!中已经有很好的解释,我翻译一下:
在 MRO 中,基类永远出现在派生类后面,如果有多个基类,基类的相对顺序保持不变。

最后的最后,提醒大家.
什么 super 啊,MRO 啊,都是针对 new-style class。如果不是 new-style class,就老老实实用父类的类名去调用函数吧。

--
更新,回答

的问题。

class A(object) :
def __init__(self, strName, *args) :
self.name = strName
super(A, self).__init__(*args) class B(object) :
def __init__(self, iID) :
self.ID= iID class C(A, B):
def __init__(self, *args)
super(C, self).__init__(*args)

没有考虑 keyword 参数,如果要要考虑,也是类似的,加后面就行了

python中super的理解(转)的更多相关文章

  1. Java 泛型 <? super T> 中 super 怎么 理解?与 < ? extends T>有何不同?

    Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同? 简介 前两篇文章介绍了泛型的基本用法.类型擦除以及泛型数组.在泛型的使用中,还有个重要的 ...

  2. python中super().__init__和类名.__init__的区别

    super().__init__相对于类名.__init__,在单继承上用法基本无差 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次 多继承时 ...

  3. Python中super的用法【转载】

    Python中super的用法[转载] 转载dxk_093812 最后发布于2019-02-17 20:12:18 阅读数 1143  收藏 展开 转载自 Python面向对象中super用法与MRO ...

  4. python中super()的一些用法

    在看python高级编程这本书的时候,在讲到super的时候,产生了一些疑惑,super在python中的用法跟其他的语言有一些不一样的地方,在网上找了一些资料,发现基本上很少有文章能把我的疑惑讲明白 ...

  5. Python中super函数的用法

    之前看python文档的时候发现许多单继承类也用了super()来申明父类,那么这样做有何意义? 从python官网文档对于super的介绍来看,其作用为返回一个代理对象作为代表调用父类或亲类方法.( ...

  6. Python中super()的用法

    参考链接:https://www.cnblogs.com/shengulong/p/7892266.html super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是 ...

  7. Python中super的应用

    约定 单继承 多继承 super 是个类 多继承中 super 的工作方式 参考资料 约定 在开始之前我们来约定一下本文所使用的 Python 版本.默认用的是 Python 3,也就是说:本文所定义 ...

  8. Python中super详解

    转至:https://mozillazg.com/2016/12/python-super-is-not-as-simple-as-you-thought.html 说到 super, 大家可能觉得很 ...

  9. Python中使用@的理解

    Python函数中使用@ 稍提一下的基础 fun 和fun()的区别 以一段代码为例: def fun(): print('fun') return None a = fun() #fun函数并将返回 ...

随机推荐

  1. linux计算服务器最近一次重启的时间

    date -d "$(awk -F. '{print $1}' /proc/uptime) second ago" +"%Y-%m-%d %H:%M:%S" 这 ...

  2. thinkphp (tcms)

    使用的是:3.2.3模板: js获取thinkphp数组时:var obj = {:json_encode($obj)}: 转成js对象:进而再处理: 创建公共控制器: thinkphp:ajax返回 ...

  3. winform数据存储的方式

    存储的方式有三种: 一.SQL数据库 二.Access(office 2007版本以上是需要安装驱动的) 三.XML

  4. 【MySql】join操作

    飞机票 飞机票 加油 INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录. LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录. RIGHT JOIN( ...

  5. Java 银联支付官网demo测试及项目整合代码

    注:原文来源与 < Java 银联支付官网demo测试及项目整合代码  > 银联支付(网关支付B2C) 一.测试官网demo a)下载官网开发包,导入eclipse等待修改(下载的开发包没 ...

  6. Python yield使用浅析

    yield可将一个函数变成生成器,每次调用时,返回yield的结果,下次迭代时,从yield 下条语句开始执行. 一个典型的例子,斐波拉切数列: def fab(max): n, a, b = 0, ...

  7. linux命令中的参数前的一横(-)和两横(--)的区别

    在解释这些区别之前我们先了解一下有关linux的背景知识,这个需要大家先认真看完就会对这些区别有更深入的了解,对linux也有更深的了解. 关于System V和BSD风格以及他们与Linux的关系: ...

  8. Vue+restfulframework示例

    一.简单回顾vue 前不久我们已经了解了vue前端框架,所以现在强调几点: 修改源: npm config set registry https://registry.npm.taobao.org 创 ...

  9. 《剑指offer》 二维数组中的查找

    本题目是<剑指offer>中的题目 二维数组中的查找 题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个 ...

  10. 常用的Eclipse 快捷键

    显示所有快捷方式 SHIFT + CTRL + L 代码类 ALT + / 代码补全 ALT + 1 批量修改变量名 SHIFT + CTRL + F 自动格式代码4 SHIFT + ALT + R ...