我们最常见的,可以说几乎唯一能见到的使用super的形式是:

class SubClass(BaseClass):
def method(self):
super(SubClass, self).method()
#do some thing here...

其中,最常见的method()是__init__()

以前做过Java,刚刚接触Python的继承,的确感觉有点奇怪,有时候还能搞混。。。当然这还是因为Java是单继承,只能用接口实现类似多继承的方式,而Python就直接支持多继承。

当我第一次见到这个super()的时候,我想说,这是啥啊?为什么Python的super看起来这么奇怪呢?
super直接指向父类的实例不就得了么?为什么非得搞两个参数?
而且第一个参数还是自己的类名,而不是父类的类名!
既然是自己的类名你还费劲写一遍干嘛,干脆省略不得了?
第二个参数为啥是self?既然是self你省略不得了?
还有,super()返回的是个啥玩意啊,为什么可以.method() ? 难道他返回了一个BaseClass的instance么?
 
今天就来解答这一连串的问题。
 

1)super直接指向父类的实例不就得了么?

首先是不能指向,因为子类实例里面根本就没有一个父类实例,这跟java是不同的。详细看这里
其次是即便像我们想象的,子类实例里有一个叫super的指针,指向父类的实例(这个父类实例在子类实例生成的时候自动生成了,是子类实例的一个‘成员’)。
但是由于多继承的存在,还是会有问题。这也是跟java不同,java不支持多继承,java用接口的方式实现多继承。
举个例子:
当只存在单继承的时候,一切很美好,就像java一样:

你只需要在重写方法的时候,用super去调用父类的方法,然后再做自己的事就可以了。
 
但是在多继承的情况下,一切都不美好了:
 

当艺人展示自己能力的时候,他说,父亲啊,你先展示自己的能力,然后我来!
但是父亲是谁? 他有两个父亲! 总不能写两遍 super.展示自己 吧?
那么我们自然想到,给super搞一个参数不得了,指出super的是哪个父类。
比如 super(歌手).展示自己(),super(演员).展示自己(),好像一切又可以美好了:
 

先不说这种写法多么的丑陋,重复了那么多无意义的、类似的行,单说这种方法根本就行不通。

我们看看如果某个艺人的实例调用了.展示能力() ,将会输出什么:
我是人类,我能走路!
我是歌手,我能唱歌!
我是人类,我能走路!
我是演员,我能演戏!
我是艺人,我能代言广告!
有必要告诉大家两遍你是个人类么?这要是一个又身兼了主持人的艺人,岂不是得大声宣布三次自己是个人类??
这显然是不好的。
 
而且,这只是其一,假设多说了几遍自己是人类你也能忍,那么还有一种情况,更糟。
你比如说,艺人类没有重写 展现自己() 这个方法,当你用艺人的实例去调用 展现自己()的时候,将会发生啥?
不重写的方法自动调用父类的,但是有两个父类呀!调用哪个的呢?任意调用一个(比如按从左到右的顺序)?
那么体现不出他另一个父类的特点呀!比如调用歌手类的,那只能体现出这个艺人既是个歌手,又是个人类,根本体现不出他是个演员!
两个都调用?那万一其中一个父类没有这个方法呢?而且先调用哪个后调用哪个?按照左右顺序么?
总之这样很乱,编译器表示压力很大。
 

 
 
所以,python的super()用了两个参数。
先写在这里:
 
super(SubClass, self).method() 的意思是,根据self去找SubClass的‘父亲’,然后调用这个‘父亲’的method()
 
最最重点的地方来了:对于一个类来说,它的‘父类’到底是谁,取决于站在谁的角度去看。
 
 

‘父亲’之所以加了引号,是因为‘父亲’并不一定是上下级的继承关系,很可能只是兄弟。比如上图中歌手的‘父亲’是‘演员’,但实际上他们是兄弟关系。
所以以后用‘下一个类’来代替这个带引号的‘父亲’。
 
总之,站在不同的实例的角度,看到的‘下一个类’是不同的。
 
这就是super()第二个参数————self 的意义。
如果是一个歌手实例调用的,那么self=歌手实例,super()将站在一个歌手的角度,去找歌手类的‘下一个类’,则会找到人类;

如果是一个艺人实例调用的,那么self=艺人实例,super()将站在一个艺人的角度,去找歌手类的‘下一个类’,则会找到演员。

 
 代码如下:
class People(object):
def show_my_power(self):
print(u"I am a people, I can walk !") class Singer(People):
def show_my_power(self):
super(Singer, self).show_my_power()
print(u"I am a singer, I can sing !") class Actor(People):
def show_my_power(self):
super(Actor, self).show_my_power()
print(u"I am an actor, I can act !") class Artist(Singer, Actor):
pass if __name__ == "__main__":
a = Artist()
a.show_my_power()

运行结果:

I am a people, I can walk !
I am an actor, I can act !
I am a singer, I can sing !
这里需要注意:当一个类从多个类继承的时候,按照从左到右的顺序。
也就是说,站在艺人的角度,首先看到艺人类的‘下一个类’是歌手类,然后歌手类的‘下一个类’是演员类。
这是因为歌手写在了左边:Artist(Singer, Actor)

看一下上面代码的执行过程吧:

由于 super() 绝大多数时候,都在咱们开篇说的这种情况下使用,即在类的定义语句块内部写:super(本类名,self)
所以 python3 做了个简化,如果你在类定义的语句块内写一个不带参数的super(),则相当于写了 super(本类名,self)
 

因为 super() 不光可以用在类的定义内部,所以,这种方便仅在类定义体内部有效。

参考

 

Python面试题之Python的Super方法的更多相关文章

  1. 千万不要错过这几道Python面试题,Python面试题No16

    第1题: python下多线程的限制以及多进程中传递参数的方式? python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性, ...

  2. Python面试题之Python和Java中Super方法的区别

    python 的 super 是一个函数,需要两个参数,第一个参数是类,第二个参数是实例,返回值是一个类对象. 其意义是:站在参数2这个实例的角度看去, 参数1这个类的‘父亲’是谁,把‘父亲’返回. ...

  3. Python面试题之Python面试题汇总

    在这篇文章中: Python基础篇 1:为什么学习Python 2:通过什么途径学习Python 3:谈谈对Python和其他语言的区别 Python的优势: 4:简述解释型和编译型编程语言 5:Py ...

  4. Python面试题之Python面向对象编程汇总

    面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的.Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念, ...

  5. python面试题二:Python 基础题

    1.位和字节的关系? Byte 字节 bit 位 1Byte = 8bit 2.b.B.KB.MB.GB 的关系? 1Byte = 8bit KB 1KB=1024B MB 1MB=1024KB GB ...

  6. python面试题之Python支持什么数据类型?

    所属网站分类: 面试经典 > python 作者:外星人入侵 链接:http://www.pythonheidong.com/blog/article/67/ 来源:python黑洞网,专注py ...

  7. python面试题之Python如何实现单例模式?

    #使用__metaclass__(元类)的高级python用法 class Singleton2(type): def __init__(cls, name, bases, dict): super( ...

  8. python面试题三:Python 网络编程与并发

    1 简述 OSI 七层协议. OSI七层协议模型主要是: 应用层(Application):为用户的应用程序(例如电子邮件.文件传输和终端仿真)提供网络服务. 表示层(Presentation):使用 ...

  9. Python面试题之python是一种什么语言及优缺点

    1.说说python是一种什么语言? 参考答案:python是一门动态解释性的强类型定义语言 编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译 ...

随机推荐

  1. 维纳滤波和编码曝光PSF去除运动模糊【matlab】

    编码曝光知识 - ostartech - 博客园 https://www.cnblogs.com/wxl845235800/p/8276362.html %%%%%%%%%%%%%%%%%%%%%%% ...

  2. css各居中大法

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  3. 分布式服务框架dubbo入门实例

    dubbo是一个分布式的服务架构,可直接用于生产环境作为SOA服务框架. 官网首页:http://dubbo.io/ ,官方用户指南 http://dubbo.io/User+Guide-zh.htm ...

  4. C语言函数重入

    C语言函数重入 可重入函数:可以被中断的函数,即这个函数执行时,可以中断其执行,可以由一个或多个任务并发使用,而不比担心数据错误. 不可重入函数(不安全函数) 不能运行在多任务环境下,除非能保证互斥( ...

  5. 分布式服务框架:Zookeeper简介

    分布式服务框架:Zookeeper(分布式系统的可靠协调系统) 本文导读: 1 Zookeeper概述 2 Zookeeper总体结构 ——逻辑图.运转流程.特点.优点.数据结构 3 Zookeepe ...

  6. poj万人题

    poj提交数量过万的题,除了水爆了的题就是无比经典的,不得不刷的题. 准备将poj上提交次数过万的题刷个遍. 持续更新中... poj 2828(线段树) 此题乃是Zhu, Zeyuan神牛出的,拿到 ...

  7. Django 中的自定义分页标签

    目录结构: 1.在应用下,migrations的同级目录创建templatetags目录(主要两个文件,包含__init__.py) 2.创建分页标签(pagetag.py) #!/usr/bin/e ...

  8. 向spider中传递参数

    1.这里采用run.py脚本方式 # 通过CrawlerProcess同时运行几个spider import scrapy from scrapy.crawler import CrawlerProc ...

  9. MySQL 1067

    今天在云服务器上装mysql的时候,启动突然报了一个“1067 进程意外终止”的错误,这个错误之前是遇到过的,之前因为my.ini配置basedir路径的时候没有正确配置导致了这个错误,但是今天又出现 ...

  10. Phonetic Symbols:2个半元音:[w] ,[j]

    2个半元音音标发音技巧与单词举例 原文地址:http://www.hlyy.in/1243.html 2个半元音音标发音技巧与半元音单词举例 [w]  发音技巧: 嘴唇张开到刚好可以含住一根吸管的程度 ...