WOW!!!

这里wow的是真尼玛绕且没看完,

好困呐,贴上网址,等自己英文好一点再看(https://rhettinger.wordpress.com/2011/05/26/super-considered-super/),,,,

自己的理解:

先上例子:

例1:

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"

输出:

 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

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

这是为什么呢?

super不是简单地调用所谓基类的方法,而是调用MRO中的下一个类的方法,也就是类似于next的方法。

mro中记录了一个类的所有基类的类类型序列。查看mro的记录,发觉包含7个元素,7个类名分别为:F E B C D A object

从而说明了为什么在C.__init__中使用super(C, self).__init__()会调用类D的初始化函数了。

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

MRO & super

Method resolution order是python用来解析方法调用顺序的。MRO对于多重继承中方法调用异常重要。python中有一个内建函数和MRO密切相关——super。具体实现方式,有兴趣可以以后看看。

在 MRO 中,基类永远出现在派生类后面,如果有多个基类,基类的相对顺序保持不变。

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的作用是什么呢?

按名字继承的话,如果子类的父类发生变化时,必须要全部替换名字,比较麻烦;

  

如果没有复杂的继承结构,super 作用不大。

例2:(没太看懂这货)

class A(object):
def __init__(self):
print "enter A"
super(A, self).__init__() # new 寄几继承寄几是什么鬼?
print "leave A" class B(object):
def __init__(self):
print "enter B"
super(B, self).__init__() # new
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"
super(E, self).__init__() # change
print "leave E" class F(E, D):
def __init__(self):
print "enter F"
super(F, self).__init__() # change
print "leave F"

输出:

 enter F
enter E
enter B
enter C
enter D
enter A
leave A
leave D
leave C
leave B
leave E
leave F

明显地,F的初始化不仅完成了所有的父类的调用,而且保证了每一个父类的初始化函数只调用一次。

那么,总结:

1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数, 产生了一个super对象;

2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;

3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;

4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super);

    如果类被设计成使用了super,那么所有子类也必须要调用super,否则直接调用会出现重复调用的问题

5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。(保持一致性。要不全部用类名调用父类,要不就全部用 super,不要一半一半。)

参考:

http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html(super)

http://blog.csdn.net/rommi/article/details/51058360(MRO)

http://blog.csdn.net/seizef/article/details/5310107(super & MRO)


Python 之 super & MRO (没有遇到过适用场景)的更多相关文章

  1. 由Python的super()函数想到的

    python-super *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...

  2. 关于Python的super用法研究

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A:  def __init__(se ...

  3. Python: 你不知道的 super

    https://segmentfault.com/a/1190000007426467 Python: 你不知道的 super 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我 ...

  4. python中super的理解(转)

    原文地址:https://www.zhihu.com/question/20040039 针对你的问题,答案是可以,并没有区别.但是这题下的回答我感觉都不够好. 要谈论 super,首先我们应该无视 ...

  5. python的super函数学习

    一.为什么要用super? 在Python 2.2以前,通常的做法: class A: def __init__(self): print "enter A" print &quo ...

  6. Python’s super() considered super!

    如果你没有被Python的super()惊愕过,那么要么是你不了解它的威力,要么就是你不知道如何高效地使用它. 有许多介绍super()的文章,这一篇与其它文章的不同之处在于: 提供了实例 阐述了它的 ...

  7. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

  8. python的super深入了解(转)

    1.python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通方法和super方法 假设Base是基类 class Base(object): def __init__(s ...

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

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

随机推荐

  1. Reverse链表 非递归实现

    #include<iostream> struct node{ int payload; node* next; }; void bianli(node* head){ node* ite ...

  2. mac 端口转发方案

    mac 端口映射 好坑 osx10.10mac移除了ipfw改用pfpf以前没用过 查文档mac的 pf语法,没有找到.bsd的倒是很全,心喜拿来一试.http://www.openbsd.org/f ...

  3. Quartz.net 定时调度CronTrigger时间配置格式说明

    1.   CronTrigger时间格式配置说明 CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 ...

  4. JavaScript基础知识整理(1)

    粗略理解,努力入门中 1.在html中引入外部脚本:  <script src="filename.js"></script> 2.注释:  多于一行的长注 ...

  5. 第八章 springboot + mybatis + 多数据源(转载)

    本篇博客转发自:http://www.cnblogs.com/java-zhao/p/5413845.html 在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构 ...

  6. 说说C#的async和await 解决卡顿问题 转

    C# 5.0中引入了async 和 await.这两个关键字可以让你更方便的写出异步代码. 看个例子: 可以看到,async和await关键字只是把上面的代码变得更简单易懂而已. public cla ...

  7. c#在主窗体panel 容器内嵌入另一个窗体(子窗体)的实现

    主窗体:  子窗体: 把子窗体嵌入到主窗体的panel 右侧中: 代码: { public MainForm() { InitializeComponent(); } private void Clo ...

  8. Sprint3(12.18)总结

    Sprint3第三阶段 1.类名:软件工程-第三阶段 2.时间:至12.18 3.选题内容:web版-餐厅到店点餐系统 4.团队博客地址: http://www.cnblogs.com/queenju ...

  9. 转载:JAVA中关于set()和get()方法的理解及使用

    对于JAVA初学者来说,set和get这两个方法似乎已经很熟悉了,这两个方法是JAVA变成中的基本用法,也是出现频率相当高的两个方法. 为了让JAVA初学者能更好的理解这两个方法的使用和意义,今天笔者 ...

  10. VS2012常用快捷键

    Ctrl+K,D ----格式化全部代码 Ctrl+K,F ----格式化选中的代码 Ctrl+K,C ----注释选定内容 Ctrl+K,U ----取消注释选定内容 Ctrl+J或者 Ctrl+S ...