iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0

多重繼承

繼承,只的是單繼承(1對1)。但多重繼承比較接近多型,因為它會分為多調一或一調多。這樣就會牽扯到MRO(方法順序),但不管哪一個;都會繼承主類別(class)的特性。

#一調多
class A:
    print('A')
class B:
    print('B')
class C:
    print('C')

class D(A, B, C):
    pass
D()
#多調一
class A:
    print('all_ABCD')
class B(A):
    pass
class C(A):
    pass
class D(A):
    pass
B() , C() , D()

之前有提到super()函式,它的主要目的不是為了簡化。而是處理多承的問題
像__init__它是class第一個呼叫的名稱,但一個class只能呼叫一個__init__,這時運用super()就可解決(破除名稱唯一性)。

class A:
    def __init__(self):
        self.a = "A"
    def fc_a(self):
        print(self.a)

class B:
    def __init__(self):
        self.b = "B"
    def fc_b(self):
        print(self.b)

class C:
    def __init__(self):
        self.c = "C"
    def fc_c(self):
        print(self.c)

class D(A, B, C):
    def __init__(self):
        super().__init__()
        super(A, self).__init__()
        super(B, self).__init__()
        super(C, self).__init__() #super調用每個class內指定__init__
d = D()
d.fc_a()
d.fc_b()
d.fc_c()

每個繼承都有__init__,到底要看哪個子繼承呢?透過super()的安排就能把第一個回傳class轉為子繼承的class。

  • 初始化class

class bank(object):
    #每次執行都返回__init__ 把acct跟pwd 初始化為0
    def __init__(self, acct=None , pwd=None): 
        self.acct = acct
        self.pwd = pwd
    def sss(self):
        print(f'welcome~{self.acct}')
        print(f'pwd is {self.pwd}')
class DB(bank):
    def code(self):
        super().sss()
d = DB()
print('初始化為:')
d.code()

這樣繼承時也可延續主要class的『模板』,也是一種使程式更簡潔的用法。
這種用法常配合陣列把資料存進去,類似資料庫的方法


MRO(方法順序)

假如有個多重繼承同時要讓所有子class輸出,會發現輸出跟原程式輸出順序不同。
沒錯,因為每個輸出都會因繼承方法而影響屬性(權限高低)而有不同的輸出。此為MRO(方法解析順序)
查詢方法:使用__mro__來讀取繼承順序

class A():
    print('all_ABCD')
    def A_fc(self):
        print('A_fc')
class B(C):
    print('B_class')
class C(A):
    print('C_class')
class D(B , A):
    pass
print(A.__mro__,'\n',B.__mro__,'\n',C.__mro__,'\n',D.__mro__)

=> 代表繼承

A => init
B => C => A => init
C => A => init
D => B => C => A => A(遞迴) => init

  • c3線性化

python2.3之後就改進了以往其他程式語言的邏輯 讓程式有了人類的繼承邏輯。如有繼承的衝突,它會報錯。此稱為c3線性化

class A():
    print('all_ABCD')
    def __init__(self):
        print('__init__')
class B(A , C , B):
    print('B_class')
class C(A ,D , C):
    print('C_class')
class D(B ,A,D):
    pass
print(B.__mro__,'\n',C.__mro__,'\n',A.__mro__,'\n',D.__mro__)

Out[ ]:TypeError: Cannot create a consistent method resolution
        order (MRO) for bases object, B, C

上一篇
[D17] OOP之設計2
下一篇
[D19] python資料型別
系列文
從寫程式到脫離菜雞的歷練(以python為主的資處與檔案權限)32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言