下面这个URL解释得比较清楚。

http://python.jobbole.com/86787/?utm_source=group.jobbole.com&utm_medium=relatedArticles

================

首先得说明的是,Python的类分为经典类 和 新式类
经典类是python2.2之前的东西,但是在2.7还在兼容,但是在3之后的版本就只承认新式类了
新式类在python2.2之后的版本中都可以使用

经典类和新式类的区别在于:

  1. 经典类是默认没有派生自某个基类的,而新式类是默认派生自object这个基类的:
 
 
1
2
3
4
5
6
# old style
class A():pass
 
# new style
class A(obejct):pass
 

2.经典类在类多重继承的时候是采用从左到右深度优先原则匹配方法的..而新式类是采用C3算法(不同于广度优先)进行匹配的

3.经典类是没有__MRO__和instance.mro()调用的,而新式类是有的.

为什么不用经典类,要更换到新式类

因为在经典类中的多重继承会有些问题…可能导致在继承树中的方法查询绕过后面的父类:

在经典类中,你如果要访问父类的话,是用类名来访问的..

 
 
1
2
3
4
5
6
7
8
class A():
    def __init__(self):
        print "A"
class B(A):
    def __init__(self):
        print "B"
        A.__init__(self)  #python不会默认调用父类的初始化函数的
 

这样子看起来没三问题,但是如果类的继承结构比较复杂,会导致代码的可维护性很差..
所以新式类推出了super这个东西…

 
 
1
2
3
4
5
6
7
8
class A():
    def __init__(self):
        print "A"
class B(A):
    def __init__(self):
        print "B"
        super(B,self).__init__()
 

事实上,对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了类继承的顺序,我们可以使用下面的方式获得某个类的 MRO 列表:

那这个 MRO 列表的顺序是怎么定的呢,它是通过一个 C3 线性化算法来实现的,这里我们就不去深究这个算法了,感兴趣的读者可以自己去了解一下,总的来说,一个类的 MRO 列表就是合并所有父类的 MRO 列表,并遵循以下三条原则:

  • 子类永远在父类前面
  • 如果有多个父类,会根据它们在列表中的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类

最佳实现:

  1. 避免多重继承
  2. super使用一致
  3. 不要混用经典类和新式类
  4. 调用父类的时候注意检查类层次

小结

  • 事实上,super 和父类没有实质性的关联。
  • super(cls, inst) 获得的是 cls 在 inst 的 MRO 列表中的下一个类。

测试代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Base(object):
    def __init__(self):
        print 'enter base'
        print 'leave base'

class A(Base):
    def __init__(self):
        print 'enter A'
        super(A, self).__init__()
        print 'leave A'

class B(Base):
    def __init__(self):
        print 'enter B'
        super(B, self).__init__()
        print 'leave B'

class C(A, B):
    def __init__(self):
        print 'enter C'
        super(C, self).__init__()
        print 'leave C'

print C.mro()
print C()

输出:

python类中的super,原理如何?MRO是什么东东?的更多相关文章

  1. Python类中super()和__init__()的关系

    Python类中super()和__init__()的关系 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(sel ...

  2. 【转】python类中super()和__init__()的区别

    [转]python类中super()和__init__()的区别 单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(se ...

  3. 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法

    第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一.    案例说明 本节定义了类Sta ...

  4. 第7.14节 Python类中的实例方法详析

    第7.14节 Python类中的实例方法详析 一.    实例方法的定义 在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式: 1.    类体中定义实例方法 第一种方式很简单,就是在类体 ...

  5. 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑

    上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...

  6. Python类中的self到底是干啥的

    Python类中的self到底是干啥的 Python编写类的时候,每个函数参数第一个参数都是self,一开始我不管它到底是干嘛的,只知道必须要写上.后来对Python渐渐熟悉了一点,再回头看self的 ...

  7. 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘

    孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...

  8. Python 简明教程 --- 20,Python 类中的属性与方法

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 与客户保持良好的关系可以使生产率加倍. -- Larry Bernstain 目录 类中的变量称为属 ...

  9. 第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析

    第7.17节  Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析 静态方法也是通过类定义的一种方法,一般将不需要访问类属性但是类需要具有的一些能力可以静态方法提供. 一 ...

随机推荐

  1. (转)listview中常见难题总结

    原文地址:http://blog.csdn.net/cherry609195946/article/details/8844224 1. PopWindow中listview的item获取不到点击事件 ...

  2. Delphi中Interface接口的使用方法

    示例注释(现在应该知道的): {   1.接口命名约定 I 起头, 就像类从 T 打头一样.   2.接口都是从 IInterface 继承而来; 若是从根接口继承, 可省略.   3.接口成员只能是 ...

  3. 八数码问题:C++广度搜索实现

    毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...

  4. 3 EventTime 事件时间类和TimeNow函数——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 这里是时间相关类的第三个部分,也是最后一个部分. EventTime 事件时间类 这个类和Dela ...

  5. 微博地址url(id)与mid的相互转换 Java版

    原理: 新浪微博的URL都是如:http://weibo.com/2480531040/z8ElgBLeQ这样三部分. 第一部分(绿色部分)为新浪微博的域名,第二部分(红色部分)为博主Uid,第三部分 ...

  6. Hibernate 多对多关联查询条件使用

    from Brand as b inner join fetch b.styles as s where s.styleId=?

  7. Python 正则表达式:只要整数和小数

    要求用户只能输入数字(包括整数和小数),如何用正则表达式验证用户输入? 有两种思路: 1. 给出正确格式的正则表达式,然后看输入是否合法. 2. 列出所有错误的输入,看输入是否非法. 对于思路1,想想 ...

  8. PHP使用curl替代file_get_contents

    初学php的朋友们,很容易翻一个错误,在写采集程序或者调用api接口总会有线考虑到使用file_get_contents函数来或许内容,程序的访问量不大倒是没什么影响,但是访问量提升了那非常的悲剧了, ...

  9. 【Unity3D】Invoke,InvokeRepeating ,Coroutine 延迟调用,周期性调用

    Invoke和InvokeRepeating方法,可以实现延迟调用,和周期调用 第一个是执行一次,第二个是重复执行 void Invoke(string methodName, float time) ...

  10. web开发架构设计

    2015-07-31 13:10:38 一, web服务器 .负载均衡 .不做对URL的rewrite逻辑判断, 全部转发到代码服务器的单一入口文件, 由代码去全权处理 二, 代码服务器(常跟web服 ...