python 继承中的super
python继承中子类访问父类的方法(包括__init__)主要有两种方法,一种是调用父类的未绑定方法,另一种是使用super(仅仅对于新式类),看下面的两个例子:
#coding:utf-8 class Father(object): #继承自object,使用新式类
def hello(self, name):
print 'i am ' + name + ' from Father ' class Son(Father):
def hello(self, name):
print 'i am ' + name + ' from Son'
Father.hello(self, name) # 使用父类的未绑定方法
super(Son, self).hello(name) #使用super来调用 s = Son()
s.hello('zhangsan')
对于super的使用其实牵扯到一个MRO的问题,尤其在多重继承的时候尤为重要。先看一个最简单的多继承的例子:
#coding:utf-8
class A(object):
def __init__(self):
print '>> A' class B(object):
def __init__(self):
print '>> B' class C(A, B):
def __init__(self):
super(C, self).__init__()
print '>> C' C()
结果为:
>> A
>> C
我们发现并没有访问到B的__init__方法。
C.mro() 返回 [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>] ( C --> A --> B --> object) , 当我们使用super时就是按照这个顺序来执行方法,
super(C, self).__init__()其实执行的是A的__init__方法,如果我们希望继续执行B的__init__方法,那么就必须在A的__init__方法中添加super调用,如果继承体系更加复杂,以此类推。 现在我们在A中加入super方法。
#coding:utf-8
class A(object):
def __init__(self):
super(A, self).__init__() #在A中新加入super方法
print '>> A' class B(object):
def __init__(self):
print '>> B' class C(A, B):
def __init__(self):
super(C, self).__init__()
print '>> C' C()
执行的结果就是:
>> B
>> A
>> C
如果我们把C(A,B)改为C(B, A),也就是改变C的继承顺序,那么C的mro顺序就是( C --> B --> A --> object), 在C中的super会调用B, B中的super会调用A, 所以我们要希望同时调用A B的__init__就必须再在B中加入super调用,此时A中的super可有可无,它其实是调用object的__init__。
#coding:utf-8
class A(object):
def __init__(self):
#super(A, self).__init__() #在A中不再需要super
print '>> A' class B(object):
def __init__(self):
super(B, self).__init__() #在B中加入super调用
print '>> B' class C(B, A): #改变C的继承顺序为 B, A
def __init__(self):
super(C, self).__init__()
print '>> C' C()
结果为:
>> A
>> B
>> C
总结一下: 使用super时,是按照MRO顺序来寻找调用的是继承体系中的哪个方法。
上面的例子是构造方法,看下面的普通方法的使用:
#coding:utf-8
class A(object):
def hello(self):
super(A, self).hello()
print '>> A' class B(object):
def hello(self):
print '>> B' class C(A, B):
def hello(self):
super(C, self).hello()
print '>> C' c = C()
c.hello() '''
>> B
>> A
>> C
''' a = A()
a.hello() #AttributeError: 'super' object has no attribute 'hello'
上面的例子中,我希望在C中hello方法中同时调用A B的hello方法,c.hello()这样调用的确是可行的,会依次调用C -》 A -》 B的hello方法, 但是在A的hello方法中使用super是有隐患的,在A的实例上直接调用hello就会报错,因为此时是去调用object的hello方法,而object没有hello方法。
而且在多重继承中使用super时,如果传递参数也会很别扭:
#coding:utf-8
class A(object):
def __init__(self, name):
super(A, self).__init__(11) # 希望初始化B, 就必须在A 中传递具体参数,很显然不可取
self.name = name class B(object):
def __init__(self, age):
self.age = age class C(A, B):
def __init__(self):
super(C, self).__init__('zhangsan') #在C中只能够初始化A c = C()
print c.name, c.age
在上面的例子中, C的父类A需要初始化name属性,父类B需要初始化age属性,在C中使用super仅仅能够初始化A中的name,对B没法处理,必须在A中去初始化B的age属性,这很明显是不可取得。
上面提到的这些问题,在单继承中都是不存在的。
我对python的多继承理解的并不深入,这篇文章主要说明了多继承中使用super的一些问题,其实我觉得还是尽量少用多继承为好。
python 继承中的super的更多相关文章
- python类中的super,原理如何?MRO是什么东东?
下面这个URL解释得比较清楚. http://python.jobbole.com/86787/?utm_source=group.jobbole.com&utm_medium=related ...
- 关于继承中的super()调用父类构造方法
super super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类. 每当你new一个子类对象的时候,子类对象都隐式内置了一个父类对象.所以说,为了那个内置的父类 ...
- java继承中关于super关键字和this关键字的使用
1.super关键字 由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字.super 可以用来访问父类的构造方法.普通方法和属性.super 关键字的功能: ...
- python之类中的super函数
作用 实现代码重用 思考:super真的只是调用父类么? super函数是按照mro算法去调用的,不bb上代码: class A: def __init__(self): print('A') cla ...
- python 继承中的__init__
如果子类不重写__init__, 实例化子类时,会自动调用父类定义的__init__ 如果子类要重写__init__,实例化子类,就不会调用父类已经定义的__init__ 所以如果想要扩充父类,需要显 ...
- Python面向对象中super用法与MRO机制
1. 引言 最近在研究django rest_framework的源码,老是遇到super,搞得一团蒙,多番查看各路大神博客,总算明白了一点,今天做一点总结. 2. 为什么要用super 1)让代码维 ...
- Python - 面向对象编程 - 使用 super() 的一些注意事项
super() 详解 https://www.cnblogs.com/poloyy/p/15223443.html 多继承中使用 super() class A: def test(self): pr ...
- Python进阶-继承中的MRO与super
Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...
- python 中的super()继承,搜索广度为先
一.python中类的继承 1.1 单继承 在python 中我们可以这样来定义一个类:及继承它的子类 class Father: def __init__(self, mes): #1 父类的ini ...
随机推荐
- [AS3.0] NetConnection.Connect.Rejected 解决办法
以下是运用FMS录制视频的一段代码: package { import flash.display.Sprite; import flash.events.AsyncErrorEvent; impor ...
- Codeforces 28C [概率DP]
/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队 ...
- Codeforces 732e [贪心][stl乱搞]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给n个插座,m个电脑.每个插座都有一个电压,每个电脑都有需求电压. 每个插座可以接若干变压器,每个变压器可以使得电压变为x/2上取整. 有无限个变 ...
- Windows Update 时出现8024402C的错误
8024402C通常网络设置引起的问题. 你可以以管理员身份运行命令提示符,然后尝试以下操作: NETSH INT IP RESET NETSH WINHTTP RESET PROXY IPCONFI ...
- 通过创建临时表合并hive小文件
#!/bin/bash #set -x DB=$1 #获取hive表定义 ret=$(hive -e "use ${DB};show tables;"|grep -v _es|gr ...
- JS-为金额添加千分位逗号分割符
前言:这个功能在前端页面中使用的还是比较多的,正好我们的项目中也有使用此功能,不过YY同学写的代码不像个方法的样子,一个入口中间又插了几道子,所 以,我写了下面这个方法,经过测 ...
- echarts学习网站
echarts : http://echarts.baidu.com/echarts2/doc/example.html 相关脚本学习网站:http://www.jb51.net/html/list/ ...
- [转载]SVN-主干/分支
一个大项目在开发中可能会拆分成几个小项目,分别分去,同时共通的部分再由人做,做完后再统一合并.同时,在开发中,共通的部分修改后,其它人要保持同步. 这种情况反应到SVN的分支/合并功能上,再贴切不过了 ...
- Ubuntu更改鼠标灵敏度
需要命令:xinput 清自行用 man xinput 查询 xinput 帮助文档 1.插入鼠标,打开终端,输入命令:xinput 查询当前已挂在设备 2.拔出鼠标,打开终端,再输入命令:xinpu ...
- Rasterizer Stage(读书笔记3 --- Real-Time rendering)
rasterizer stage的目标:计算和设置每个像素的颜色.将屏幕空间的二维顶点和每个顶点的shading信息转换为屏幕上的像素. rasterizer stage可以分为几个阶段:triang ...