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的更多相关文章

  1. python类中的super,原理如何?MRO是什么东东?

    下面这个URL解释得比较清楚. http://python.jobbole.com/86787/?utm_source=group.jobbole.com&utm_medium=related ...

  2. 关于继承中的super()调用父类构造方法

    super super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类. 每当你new一个子类对象的时候,子类对象都隐式内置了一个父类对象.所以说,为了那个内置的父类 ...

  3. java继承中关于super关键字和this关键字的使用

    1.super关键字 由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字.super 可以用来访问父类的构造方法.普通方法和属性.super 关键字的功能: ...

  4. python之类中的super函数

    作用 实现代码重用 思考:super真的只是调用父类么? super函数是按照mro算法去调用的,不bb上代码: class A: def __init__(self): print('A') cla ...

  5. python 继承中的__init__

    如果子类不重写__init__, 实例化子类时,会自动调用父类定义的__init__ 如果子类要重写__init__,实例化子类,就不会调用父类已经定义的__init__ 所以如果想要扩充父类,需要显 ...

  6. Python面向对象中super用法与MRO机制

    1. 引言 最近在研究django rest_framework的源码,老是遇到super,搞得一团蒙,多番查看各路大神博客,总算明白了一点,今天做一点总结. 2. 为什么要用super 1)让代码维 ...

  7. Python - 面向对象编程 - 使用 super() 的一些注意事项

    super() 详解 https://www.cnblogs.com/poloyy/p/15223443.html 多继承中使用 super() class A: def test(self): pr ...

  8. Python进阶-继承中的MRO与super

    Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...

  9. python 中的super()继承,搜索广度为先

    一.python中类的继承 1.1 单继承 在python 中我们可以这样来定义一个类:及继承它的子类 class Father: def __init__(self, mes): #1 父类的ini ...

随机推荐

  1. android 代码生成selector drawable

    public static StateListDrawable makeSelector(Context context, int idNormal, int idPressed, int idFoc ...

  2. MVC表单

    .cs namespace SendToMvcHello.Controllers { public class HomeController : Controller { // GET: Home p ...

  3. java.lang.ArrayIndexOutOfBoundsException: 1

    数组越界 但是我这个也不是这个原因: 在CuiShouDetail.jsp 里,如果 添加上 QiTaDianHua,如果为空就会报错,别的都么有问题null,或者是空格,或者是有数据 1. Stri ...

  4. 同时闪烁多个要素代码(ArcEngine)

    /// <summary> /// 根据查询条件构造/// </summary> /// <param name="where">查询条件< ...

  5. 导入 RecyclerView 控件 的过程(Android 6.0)

    由于本人不熟悉Android Studio和java的思维方式,开发android studio的同事告诉我不太推荐使用ListView 而google 建议使用RecycleView ,经过了一顿查 ...

  6. setContentType、setCharacterEncoding、pageEncoding和contentType

    request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值 response.setContentType("text/html;cha ...

  7. Samba 4 Domain Controller on Ubuntu 14.04 LTS

    1. Configure network with a static ip address $sudo nano /etc/network/interfaces auto eth0 iface eth ...

  8. Ajax发送异步请求(四步操作)

    1.第一步(得到XMLHttpRequest) *ajax其实只需要学习一个对象:XMLHttpRequest,如果掌握了它,就掌握了ajax!! *得到XMLHttpRequest >大多数浏 ...

  9. 新手上路,配置阿里云CentOS服务器LAMP

    最近出了个9.9包月的阿里云一直想弄就买了个半年的,脑子一热选了个CentOS系统的然后就是无尽的代码...... 话不多说直接上步骤:  在实例中选择"连接管理终端",输入一些应 ...

  10. 样式:让div里的两个控件在一行的操作

    table的td里如果放一个text,希望在右侧再放一个按钮,让这两个控件在一行,但是放了之后总是底部不能对齐,这样的话,加上下边这句样式就可以了 position:relative; top:17p ...