Python的Super方法
我们最常见的,可以说几乎唯一能见到的使用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()将站在一个艺人的角度,去找歌手类的‘下一个类’,则会找到演员。
代码如下:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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):passif __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的Super方法相关推荐
- python之父去面试-Python面试题之Python的Super方法
当我第一次见到这个super()的时候,我想说,这是啥啊?为什么Python的super看起来这么奇怪呢? super直接指向父类的实例不就得了么?为什么非得搞两个参数? 而且第一个参数还是自己的类名 ...
- python 中super方法的调用
参考https://www.runoob.com/python/python-func-super.html 加以解释 class FooParent(object):def __init__(sel ...
- python的super方法_Python中“super”是做什么的?
有什么不同?SomeBaseClass.__init__(self) 意味着调用SomeBaseClass的__init__.而 super(Child, self).__init__() 意味着__ ...
- Python基础教程:super()方法详解
一.单独调用父类的方法 需求:编写一个类,然后再写一个子类进行继承,使用子类去调用父类的方法1. 使用方法1打印: 胖子老板,来包槟榔. 那么先写一个胖子老板的父类,执行一下: class FatFa ...
- python类的继承super方法_Python类的继承super相关原理解析
看了网上许多关于super.mro.C3的介绍感觉没有一份很容易初学者理解的文档,直接看C3算法的话,比较难理解,也没必要,如果掌握一套规律的话,会轻松许多.我将网上这些博主的文章进行一个梳理总结,最 ...
- pythonsuper继承规则,深入理解Python中的super()方法
前言 python的类分别有新式类和经典类,都支持多继承.在类的继承中,如果你想要重写父类的方法而不是覆盖的父类方法,这个时候我们可以使用super()方法来实现 python语言与C++有相似的类继 ...
- python 多继承与super使用详解_Python super()方法、多继承以及MRO顺序
仅供学习,转载请注明出处 单独调用父类的方法 需求:编写一个类,然后再写一个子类进行继承,使用子类去调用父类的方法1. 使用方法1打印: 胖子老板,来包槟榔. 那么先写一个胖子老板的父类,执行一下: ...
- python super()方法的作用_详解python的super()的作用和原理
Python中对象方法的定义很怪异,第一个参数一般都命名为self(相当于其它语言的this),用于传递对象本身,而在调用的时候则不必显式传递,系统会自动传递.uz0免费资源网 今天我们介绍的主角是s ...
- python面向编程:类继承、继承案例、单继承下属性查找、super方法
一.类的继承 二.基于继承解决类与类的代码冗余问题 三.在单继承背景下属性的查找 四.super的方法 一.类的继承 1.什么是继承? 在程序中继承是一种新建子类的方法的方式,新创建的类成为子类\派生 ...
最新文章
- ios xmlrpc
- jvm性能调优实战 - 43OOM内存溢出发生的原因及可能发生OOM的内存区域
- 【操作系统】Semaphore处理吸烟者问题
- b超可以看出什么_B超可以查出什么
- mysql投资_[Leetcode]585. 2016年的投资(MySQL)
- base64编码_动画演示 Base 64 编码
- 使用Html5+C#+微信 开发移动端游戏详细教程 :(二)准备工作开发环境
- 少儿编程scratch系统介绍(附网站源码)
- docker下修改mysql配置文件
- 基于Android的记事本APP设计与实现
- 目录_网易微专业C++系统工程师
- Flume下读取kafka数据后再打把数据输出到kafka,利用拦截器解决topic覆盖问题
- Dubbo comsumer 远程调用流程分析
- python爬取微信公众号文章
- Latex书籍模板分享
- 下载IEEE期刊Latex模板步骤
- 解决Pycharm 多线程时出现错误Process finished with exit code -1073741819 (0xC0000005)
- esp分区中的EFI启动项文件有什么用
- 用友NC65产品的对账节点联查业务帐
- IDEA断点无效问题解决办法