美文网首页
python 面向对象: super()

python 面向对象: super()

作者: snailpy | 来源:发表于2018-09-09 11:39 被阅读0次

    python 关于 super 的使用

    • 子类对象调用父类方法 :super(B,b).hh()
    • 子类中调用父类方法
      • 显示调用:B.hh(self)
      • 使用super: super(B,self).hh()
    • super调用顺序:__mro__

    面试题: 子类对象调用父类方法

    class AA(object):
        def hh(self):
            print('AA--------hh')
            
    class BB(AA):
        def hh(self):
            print('BB--------hh')
            
    b = BB()
    

    在不改造类的前提下,使用对象b 调用AAhh()方法。说实话我在python中没有这样调用过,但是隐约记得在java 中应该是直接用子类对象可以使用super来调用到父类的方法,于是就回答面试官使用b.super(BB).hh() 真的虚啊~~~。面试官说就这样吧 ~~~ 。。。。写完文章后回过来看,自己真傻叉,我记得可以使用self.super()调用啊 ,其实该方法和在类中调用一样啊 !! 抱歉小白,大家会的直接略过!!
    然后面试结束后回来自己,测试直接报错!!!,google,百度都没结果,反倒是一些super烂大街的一些使用方法,使用了Python的自省也没有发现相关的函数,翻了大概半小时让我发现了,哈哈,上代码:

    b.hh()
    super(BB,b).hh()
    输出:
    BB--------hh
    AA--------hh
    

    就是使用super(BB,b).hh() 真的没用过不知道啊

    子类中调用父类方法 烂大街用法

    显示调用父类方法:

    class AA(object):
        def hh(self,msg):
            print('AA----',msg)
    
    class BB(AA):
        def hh(self,msg):
            AA.hh(self,msg)
            print('BB----',msg)
    b = BB()
    b.hh('hello world')
    输出:
    AA---- hello world
    BB---- hello world
    

    成功调用到了父类的方法

    使用关键字super()调用父类方法:

    class AA(object):
        def hh(self,msg):
            print('AA----',msg)
            
    class CC(AA):
        def hh(self,msg):
            super(CC,self).hh(msg)
            print('CC----',msg)
    c = CC()
    c.hh('hello world')
    输出:
    AA---- hello world
    CC---- hello world
    

    同样可以成功调用父类的方法

    2种方式深入对比:显示调用

    已知有

    class AA(object):
        def hh(self,msg):
            print('AA----',msg)
    
    class BB(AA):
        def hh(self,msg):
            AA.hh(self,msg)
            print('BB----',msg)
            
    class CC(AA):
        def hh(self,msg):
            AA.hh(self,msg)
            print('CC----',msg)
    

    使用一:

    class DD(BB,CC):
        pass
    
    d = DD()
    d.hh('123')
    输出:
    AA---- 123
    BB---- 123
    

    使用二:

    class DD(BB,CC):
        def hh(self,msg):
            BB.hh(self,msg)
            CC.hh(self,msg)
    
    d = DD()
    d.hh('123')
    输出:
    AA---- 123
    BB---- 123
    AA---- 123
    CC---- 123
    

    优点:可以根据自己想要的结果具体调用某个函数,定制化程度高
    缺点:共同父类的方法会被多次调用(某些情况下可能会出错,或者效率低下)

    2种方式深入对比:super调用

    已知有:

    class AA(object):
        def hh(self,msg):
            print('AA----',msg)
    
    class BB(AA):
        def hh(self,msg):
            super(BB,self).hh(msg)
            print('BB----',msg)
            
    class CC(AA):
        def hh(self,msg):
            super(CC,self).hh(msg)
            print('CC----',msg)
    

    使用一:

    class DD(BB,CC):
        pass
        
    d = DD()
    d.hh('123')
    输出:
    AA---- 123
    CC---- 123
    BB---- 123
    

    使用二:

    class DD(BB,CC):
        def hh(self,msg):
            super(DD,self).hh(msg)
        
    d = DD()
    d.hh('123')
    输出:
    AA---- 123
    CC---- 123
    BB---- 123
    

    你会发现,俩种使用方式输出的结果是一样的,且父类的函数只调用一遍

    super调用顺序:__mro__

    在来点复杂的:

    class A(object):
        def go(self):
            print('--A')
            print("go A go!")
            print('A--')
        
    class B(A):
        def go(self):
            print('--B')
            super(B,self).go()
            print("go B go!")
            print('B--')
                
    class C(A):
        def go(self):
            print('--C')
            super(C,self).go()
            print("go C go!")
            print('C--')
                
    class D(B,C):
        def go(self):
            print('--D')
            super(D,self).go()
            print("go D go!")
            print('D--')
            
    d = D()
    d.go()
    print(D.__mro__)
    print(d.__class__.mro())
    输出:
    --D
    --B
    --C
    --A
    go A go!
    A--
    go C go!
    C--
    go B go!
    B--
    go D go!
    D--
    
    (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    

    调用顺序可谓是很诡异了。python 中对于多继承为了保证公共父类方法只被调用一次,使用了C3算法,根据某一顺序来执行继承链上的函数可以使用__mro__查看;这是个类级别的函数.
    可以看到继承链是 D-->B-->C-->A-->O输出时相当于逐链栈调用执行,等上层函数执行完才会继续执行下层函数,因此有如上输出
    想深入了解super的同学可以跳转:
    “Python’s super() Considered Super!”

    总结:

    • 子类对象调用父类方法: super(cls,self).fun(*arg)
    • pyhton 子类调用父类方法 的俩种方案
    • python 多继承调用顺序:画出继承图,从下到上,从左到右的顺序生成继承链,并以逐链栈调用的方式调用函数。

    声明:

    本人也是python 小白,对super()的使用也不是很熟练,掌握的并不好,如果上述内容有讲的不对的地方还请各位批评指点。将不胜感激,再次感谢~~~

    参考资料:

    相关文章

      网友评论

          本文标题:python 面向对象: super()

          本文链接:https://www.haomeiwen.com/subject/xvprgftx.html