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的一些问题,其实我觉得还是尽量少用多继承为好。

 

转载于:https://www.cnblogs.com/zh1164/p/6027341.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值