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 ...
随机推荐
- 【转】PL/SQL Developer各个窗口的功能
源地址:http://www.codeweblog.com/pl-sql-developer%E5%90%84%E4%B8%AA%E7%AA%97%E5%8F%A3%E7%9A%84%E5%8A%9F ...
- Linux 命令与文件的搜寻
平时会偶尔忘记一些命令或者文件,下面的这些命令能够帮我们快速的找到命令或者文件 1. 命令的搜寻 命令:which 功能:在PATH配置的目录下搜寻命令 用法:which [-a] [command] ...
- test spring in category
test tile package com.journaldev.spring.controller; import java.text.DateFormat; import java.util.Da ...
- apache httpd.conf 参数详解
由于网站需要,需要配置多个虚拟主机,但是apache主机的参数太多,记不住,下面做一下总结 归纳: ServerRoot:apache安装位置 Listen:服务器监听的端口号 LoadModule: ...
- Android常用控件及对应Robotium API
最近发现Android控件不熟悉,看Robotium的API都费劲. 常用Android控件: 控件类型 描述 相关类 Button 按钮,可以被用户按下或点击,以执行⼀个动作 Button Text ...
- Eclipse+MinGW+Boost环境搭建
一.编译 运行 .bat 生成bjam.exe 运行:bjam --build-type=complete toolset=gcc stage 二.配置 配置eclipse -L Path加入链接库位 ...
- linux中的进程和线程
应用程序:可以被操作系统执行的一组指令和参数的集合,是静态的,并存储在磁盘空间中: 进程:在操作系统中在运行程序后,处于运行状态的程序,是应用程序的一个执行过程,同时也是操作系统分配内存,cpu等系统 ...
- Openstack Day1简介及虚拟环境搭建
本文章仅作为作者本人存档记忆!恕不详细展开内容! openstack kilo版本重要组件(module)简介 ======================================= Ke ...
- 学习一下mef
微软 http://msdn.microsoft.com/zh-cn/magazine/ee291628.aspx mef http://biancheng.dnbcw.info/net/370552 ...
- Python字符串的encode与decode研究心得乱码问题解决方法
为什么Python使用过程中会出现各式各样的乱码问题,明明是中文字符却显示成“\xe4\xb8\xad\xe6\x96\x87”的形式? 为什么会报错“UnicodeEncodeError: 'asc ...