【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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM