Python中的super()

 转自:https://blog.csdn.net/weixin_41798111/article/details/117623958

super() 函数是用于调用父类(超类)的一个方法。

super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

钻石继承: 子类继承自两个单独的超类,而两个超类又继承自同一个公共基类。

 class MyBaseClass(object):
        def __init__(self, value):
            self.value = value
     
    class TimesTwo(MyBaseClass):
        def __init__(self, value):
            MyBaseClass.__init__(self,value)
            self.value *= 2
     
    class PlusFive(MyBaseClass):
        def __init__(self,value):
            MyBaseClass.__init__(self,value)
            self.value += 5
     
    class ThisWay(PlusFive,TimesTwo):
        def __init__(self, value):
            PlusFive.__init__(self, value)# value = 13
            TimesTwo.__init__(self, value) #value = 16
     
    foo = ThisWay(8)
    print(foo.value)

输出结果是16。

因为执行顺序为PlusFive的构造函数后调用基类MyBaseClass的构造函数,value=8,PLusFive构造函数value=13,执行TimeTwo的构造函数会再次调用基类MyBaseClass的构造函数value=8,再TimeTwo构造函数value=16。

 显然我们期待的是 (8+5)*2 ,原因就是构造方法中的__init__无法继承, 需要在构造函数中绑定父类中的__init__,这会导致基类的构造函数运行多次导致,为了解决这个问题,用super初始化超类,避免这种问题产生。

    class MyBaseClass(object):
        def __init__(self, value):
     
            self.value = value
     
    class TimesTwo(MyBaseClass):
        def __init__(self, value):
            super(TimesTwo, self).__init__(value)
            self.value *= 2
     
    class PlusFive(MyBaseClass):
        def __init__(self,value):
            super(PlusFive, self).__init__(value)
            self.value += 5
     
    class ThisWay(TimesTwo, PlusFive):
        def __init__(self, value):
            super(ThisWay, self).__init__(value)
     
    foo = ThisWay(8)
    print(foo.value)
     
    from pprint import pprint
    pprint(ThisWay.mro())

 

结果输出: 
26
    [<class '__main__.ThisWay'>,
     <class '__main__.TimesTwo'>,
     <class '__main__.PlusFive'>,
     <class '__main__.MyBaseClass'>,
     <class 'object'>]

如果改变ThisWay中超类定义顺序:

class ThisWay(PlusFive, TimesTwo):
    def __init__(self, value):
        super(ThisWay, self).__init__(value)
输出结果:
 21
    [<class '__main__.ThisWay'>,
     <class '__main__.PlusFive'>,
     <class '__main__.TimesTwo'>,
     <class '__main__.MyBaseClass'>,
     <class 'object'>]

结果和ThisWay定义超类顺序有关。

第一种情况先定义TimesTwo,后定义PlusFive,根据MRO可以看到初始化顺序,倒过来即是执行顺序,(8+5)*2=26。

第二种情况同理,8*2 +5 = 21

以上对super是Python2 的定义形式,比较复杂。需要指定当前类和指定相关的方法名称,这里是__init__(),以及方法的参数。

下面是Python3 定义形式:

 class MyBaseClass(object):
        def __init__(self, value):
            self.value = value
     
    class TimesTwo(MyBaseClass):
        def __init__(self, value):
            super().__init__(value)
            self.value *= 2
     
    class PlusFive(MyBaseClass):
        def __init__(self,value):
            super().__init__(value)
            self.value += 5
     
    class ThisWay(PlusFive, TimesTwo):
        def __init__(self, value):
            super().__init__(value)
     
    foo = ThisWay(8)
    print(foo.value)

 代码比较简洁。
 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值