python繼承與多重繼承

記住如下幾點:python

  • 直接子類化內置類型(如dict,liststr)容易出錯,由於內置類型的方法一般會忽略用戶覆蓋的方法,不要子類化內置類型,用戶自定義的類應該繼承collections模塊.函數

    def __setitem__(self, key, value):
            super().__setitem__(key, [value] * 2) # 錯誤案例
    
    
    class AnswerDict(dict):
        def __getitem__(self, item): # 錯誤案例
            return 42
    
    
    import collections
    
    
    class DoppelDict2(collections.UserDict): # 正確案例
        def __setitem__(self, key, value):
            super().__setitem__(key, [value] * 2)
    
    
    class AnswerDict2(collections.UserDict): # 正確案例
        def __getitem__(self, item):
            return 42
  • 多重繼承有關的另外一個問題就是:若是同級別的超類定義了同名屬性.Python如何肯定使用哪一個?post

    class DoppelDict(dict):
        def __setitem__(self, key, value):
            super().__setitem__(key, [value] * 2)
    
    
    class AnswerDict(dict):
        def __getitem__(self, item):
            return 42
    
    
    import collections
    
    
    class DoppelDict2(collections.UserDict):
        def __setitem__(self, key, value):
            super().__setitem__(key, [value] * 2)
    
    
    class AnswerDict2(collections.UserDict):
        def __getitem__(self, item):
            return 42
    
    
    class A:
        def ping(self):
            print('Ping:', self)
    
    
    class B(A):
        def pong(self):
            print('pong:', self)
    
    
    class C(A):
        def pong(self):
            print('PONG:', self)
    
    
    class D(B, C):
        def ping(self):
            super().ping()
            print('post-ping:', self)
    
        def pingpong(self):
            self.ping()
            super().ping()
            self.pong()
            super().pong()
            C.pong(self)
    if __name__ == '__main__':
    
        d = D()
        print(d.pong()) # 輸出來源於B
        print(C.pong(d)) #輸出來源於C 超類的方法均可以直接調用,此時要把實例做爲顯示參數傳入.

    python能區別調用的是哪一個方法,經過方法解析順序
    >>> D.mro()
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    若想把方法調用委託給超類,推薦的方式是使用內置的super()函數.code

    • 如下是對於d.pingpong()方法的解讀
    • >>> self.ping()
    • Ping: <__main__.D object at 0x000002213877F2B0> post-ping: <__main__.D object at 0x000002213877F2B0> 第一個調用的是self.ping(),運行的是是D類的ping,方法.
    • 第二個調用的的是super().ping(),跳過D類的ping方法,找到A類的ping方法.Ping: <__main__.D object at 0x000002213877F2B0>
    • 第三個調用的是self.pong()方法,根據__mro__,找到B類實現的pong方法. pong: <__main__.D object at 0x000002213877F2B0>
    • 第四個調用時super().pong(),也是根據__mro__,找到B類實現的pong方法. pong: <__main__.D object at 0x000002213877F2B0>
    • 第五個調用的是C.pong(self),忽略了__mro__,找到的是C類實現的pong方法. PONG: <__main__.D object at 0x000002213877F2B0>
相關文章
相關標籤/搜索