【Python】使用super初始化超类

初始化超类的传统方式,在子类的实例中调用超类的__init__()方法。

但是传统的方法有两个问题,比如:

问题1:

复制代码
 1 class MyBaseClass:
 2     def __init__(self, value):
 3         self.value = value
 4 
 5 
 6 class TimesTwo:
 7     def __init__(self):
 8         self.value *= 2
 9 
10 
11 class PlusFive:
12     def __init__(self):
13         self.value += 5
14 
15 
16 class OneWay(MyBaseClass, TimesTwo, PlusFive):
17     def __init__(self,value):
18         MyBaseClass.__init__(self, value)
19         TimesTwo.__init__(self)
20         PlusFive.__init__(self)
21 
22 
23 class AnotherWay(MyBaseClass,  PlusFive, TimesTwo):
24     def __init__(self,value):
25         MyBaseClass.__init__(self, value)
26         TimesTwo.__init__(self)
27         PlusFive.__init__(self)
28 
29 foo = OneWay(5)
30 print('OneWay (5*2)+5=', foo.value)
31 foo = AnotherWay(5)
32 print('AnotherWay:', foo.value)
复制代码

结果为:

从结果可以看出,即使改变了子类的继承顺序,调用的顺序并没有改变。

问题2:

如果子类继承自两个单独的超类,而那两个超类又继承自同一个公共基类,那么就构成了钻石型继承。

这种继承会使钻石顶端的公共基类多次执行__init__()方法,从而产生意外。

比如:

复制代码
 1 class MyBaseClass:
 2     def __init__(self, value):
 3         self.value = value
 4 
 5 
 6 class TimesFive(MyBaseClass):
 7     def __init__(self, value):
 8         MyBaseClass.__init__(self, value)
 9         self.value *= 2
10 
11 
12 class PlusTwo(MyBaseClass):
13     def __init__(self, value):
14         MyBaseClass.__init__(self, value)
15         self.value += 2
16 
17 
18 class ThisWay(TimesFive, PlusTwo):
19     def __init__(self, value):
20         TimesFive.__init__(self, value)
21         PlusTwo.__init__(self, value)
22 
23 
24 
25 foo = ThisWay(5)
26 print('Should be (5*5)+2 but is ', foo.value)
复制代码

在调用PlusTwo.__init__()时候,又一次调用MyBaseClass.__init__()又一次把value变为5

 

 

以上两种问题都可以使用super解决,方法解析顺序mro(method resolution order),以标准的流程安排超类之间的初始化顺序。

比如这次用super初始化超类

复制代码
 1 class MyBaseClass:
 2     def __init__(self, value):
 3         self.value = value
 4 
 5 
 6 class TimesFive(MyBaseClass):
 7     def __init__(self, value):
 8         super(TimesFive, self).__init__(value)
 9         self.value *= 5
10 
11 
12 class PlusTwo(MyBaseClass):
13     def __init__(self, value):
14         super(PlusTwo, self).__init__(value)
15         self.value += 2
16 
17 
18 class GoodWay(TimesFive, PlusTwo):
19     def __init__(self, value):
20         super(GoodWay, self).__init__(value)
21 
22 
23 foo = GoodWay(5)
24 print('Should be 5*(5+2) and is ', foo.value)
复制代码

并且可以使用

print(GoodWay.mro())

来查看初始化顺序:

参考资料:Effective Python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Terry_dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值