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 ...
随机推荐
- UNIX网络编程-非阻塞connect和非阻塞accept
1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长 ...
- day10-redis操作
Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...
- CentOS开机无法进入系统,如何查错
开机时按e/F5按钮,进入选择系统界面 会出现 CentOS(2.6.32-...类似的选择列表,选择默认的系统然后按e: 这时会出现 root kernel ... initd... 三个选项,选择 ...
- 使用Struts2搭建登录注册示例
使用Struts2来搭建mvc网站框架还是比较容易的,Struts2提供了各项辅助功能,保证了web开发的快速方便.下面使用struts2来搭建一个登录注册示例. 0 项目结构截图 1 搭建Strut ...
- CRM客户关系管理系统 北京易信软科信息技术有限公司
北京易信软科信息技术有限公司 推出大型erp系统,库存管理系统,客户关系管理系统,车辆登记管理系统,员工管理系统,采购管理系统,销售管理系统,为您的企业提供最优质的产品服务 北京易信软科您可信赖的北京 ...
- jeecg 扩展封装查询条件 时间段查询
使用jeecg框架开发的小伙伴们知道,添加查询条件,通常是我们加一个配置(query="true")就可以将该字段设置为查询条件.简单方便.但是这样的配置查询条件仅适用于输入框输入 ...
- pthon在Notepad++中执行方式
使用 Notepad++ 编辑运行 Python 程序 Notepad++是一个开源的文本编辑器,功能强大而且使用方便.编辑和调试 Python 程序使用什么编辑器或者 IDE不同人有 ...
- C语言中extern的用法
0x01 extern用在变量或函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”. 0x02 extern修饰变量的声明. 举例:若a.c中需引用b.c中的变量int v,可以在a. ...
- JS函数
1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head,body)4.一个浏 ...
- FAST特征点检测features2D
#include <opencv2/core/core.hpp> #include <opencv2/features2d/features2d.hpp> #include & ...