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

  • 相关阅读:
    9.27作业
    9.20作业
    9.13作业
    9.6作业
    localstorage,sessionstorage使用
    oracle 客户端重新安装遇到的问题
    HTML5学习笔记(<command>,<details>,<dialog>)
    HTML5学习笔记(HTML5新标签<bdi>)
    html5学习笔记(html5新标签<aside>)
    html5学习笔记(html5新标签<article>)
  • 原文地址:https://www.cnblogs.com/zh1164/p/6027341.html
Copyright © 2020-2023  润新知