http://hi.baidu.com/thinkinginlamp/item/3095e2f52c642516ce9f32d5

Python中对象方法的定义很怪异,第一个参数一般都命名为self(相当于其它语言的this),用于传递对象本身,而在调用的时候则不必显式传递,系统会自动传递。

举一个很常见的例子:

>>> class Foo:
    def bar(self, message):
        print(message)

>>> Foo().bar("Hello, World.")
Hello, World.

当存在继承关系的时候,有时候需要在子类中调用父类的方法,此时最简单的方法是把对象调用转换成类调用,需要注意的是这时self参数需要显式传递,例如:

>>> class FooParent:
        def bar(self, message):
            print(message)

>>> class FooChild(FooParent):
        def bar(self, message):
            FooParent.bar(self, message)

>>> FooChild().bar("Hello, World.")
Hello, World.

这样做有一些缺点,比如说如果修改了父类名称,那么在子类中会涉及多处修改,另外,Python是允许多继承的语言,如上所示的方法在多继承时就需要重复写多次,显得累赘。为了解决这些问题,Python引入了super()机制,例子代码如下:

>>> class FooParent:
        def bar(self, message):
            print(message)

>>> class FooChild(FooParent):
        def bar(self, message):
            super(FooChild, self).bar(message)

>>> FooChild().bar("Hello, World.")
Hello, World.

表面上看 super(FooChild, self).bar(message)方法和FooParent.bar(self, message)方法的结果是一致的,实际上这两种方法的内部处理机制大大不同,当涉及多继承情况时,就会表现出明显的差异来,直接给例子:

代码一:

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")

class C(A):
    def __init__(self):
        print("Enter C")
        A.__init__(self)
        print("Leave C")

class D(A):
    def __init__(self):
        print("Enter D")
        A.__init__(self)
        print("Leave D")

class E(B, C, D):
    def __init__(self):
        print("Enter E")
        B.__init__(self)
        C.__init__(self)
        D.__init__(self)
        print("Leave E")

E()

结果:

Enter E
Enter B
Enter A
Leave A
Leave B
Enter C
Enter A
Leave A
Leave C
Enter D
Enter A
Leave A
Leave D
Leave E

执行顺序很好理解,唯一需要注意的是公共父类A被执行了多次。

代码二:

class A:
    def __init__(self):
        print("Enter A")
        print("Leave A")

class B(A):
    def __init__(self):
        print("Enter B")
        super(B, self).__init__()
        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, D):
    def __init__(self):
        print("Enter E")
        super(E, self).__init__()
        print("Leave E")

E()

结果:

Enter E
Enter B
Enter C
Enter D
Enter A
Leave A
Leave D
Leave C
Leave B
Leave E

在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照mro进行的(E.__mro__)。

python super的更多相关文章

  1. Python ---- super()使用

    Python ---- super() 我们经常在类的继承当中使用super(), 来调用父类中的方法.例如下面: 1 2 3 4 5 6 7 8 9 10 11 12 13 class A:     ...

  2. Python super继承详解

    MRO(Method resolution order)是python用来解析方法调用顺序的,mro中记录了一个类的所有基类的类类型序列,super不是简单地调用基类的方法,而是按照MRO中的顺序来调 ...

  3. Python super使用

    一 基础使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: #!/usr ...

  4. python super参数错误

    # -*- coding:utf-8 _*-"""@author:Administrator@file: yamlparser.py@time: 2018/09/07&q ...

  5. python super超类方法

    super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重复调用( ...

  6. Python super() 函数的概念和例子

    概念: super() 函数是用于调用父类(超类)的一个方法. super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO).重 ...

  7. python: super原理

    super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: ...

  8. python super()函数

    super()函数是用来调用父类(超类)的一个方法 super()的语法: python 2 的用法: super(Class, self).xxx  # class是子类的名称 class A(ob ...

  9. (转)Python: super 没那么简单

    原文:https://mozillazg.com/2016/12/python-super-is-not-as-simple-as-you-thought.html python 约定¶ 单继承¶ 多 ...

随机推荐

  1. Android学习笔记之ExecutorService线程池的应用....

    PS:转眼间就开学了...都不知道这个假期到底是怎么过去的.... 学习内容: ExecutorService线程池的应用... 1.如何创建线程池... 2.调用线程池的方法,获取线程执行完毕后的结 ...

  2. API Design

    REST API Design Guidelines V 1.0.201208 Draft 5 Last Updated: 08/31/2012 1       简介 本文档旨在规范REST API的 ...

  3. Array 数组常用方法

    (1)基本的数组方法 1.join() Array.join()方法将数组中所有元素都转化为字符串并连接在一起,返回最后生成的字符串.可以自己指定分隔的符号,如果不指定,默认使用逗号 var arr ...

  4. 2015年百度之星初赛(1) --- C 序列变换

    序列变换 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. 设计模式--建造者(Builder)模式

    将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示                                                         --<设计模 ...

  6. 记录一次Mac虚拟机安装的过程(有图有真相)

    这是我今天在公司用Vmware workstation虚拟机安装小狮子的全过程,记录一下没什么特别的用途,希望以后不要忘记,整个过程我总共花了半个多小时,挺快的.确实苹果的系统配上苹果的电脑就是牛叉, ...

  7. csharp: 用Enterprise Library对象实体绑定数据

    Enterprise Library: https://msdn.microsoft.com/en-us/library/ff648951.aspx /// <summary> /// 是 ...

  8. JMS学习(三)JMS 消息结构之属性及消息体详解

    一.前言 通过上一篇的学习我们知道了消息分为三个部分,即消息头,属性及消息体,并对消息头的十个属性进行了详细的介绍,本文再对消息属性及消息体进行详细的介绍. 二.属性介绍 消息属性的主要作用是可以对头 ...

  9. Mysql的简单使用(三)

    接上文Mysql的简单使用(二) mysql中结构相同的两个表进行合并:(注意需要两个表的结构是一样的) 有如下结构的两个表father和person. 合并的步骤为: 1.把person表和fath ...

  10. Ahjesus Nodejs01 环境搭建及运行

    访问http://nodejs.org/,根据系统选择下载文件,我用的win7 64 安装一路下一步直到完成 运行cmd输入node -v查看是否安装成功 成功会显示版本号 到此环境搭建完毕 ==== ...