第12章--繼承的優缺點

第12章–繼承的優缺點

本章探討繼承和子類化,重點是說明對 Python 而言尤爲重要的兩個細節:
• 子類化內置類型的缺點–例如寫一個繼承list的列表類
• 多重繼承和方法解析順序

子類化內置類型

結論:不要子類化內置類型,而是選擇子類化collections模塊對應的類比如UserDict UserList UserStr
原因:內置類型比如list、dict使用c語言編寫的,內置類型不會調用用戶定義的類覆蓋的特殊方法
內置類型的子類覆蓋的方法會不會隱式調用,CPython 沒有制定官方規則。基本上,內置類型的方法不會調用子類覆蓋的方法。例如,dict 的子類覆蓋的
getitem() 方法不會被內置類型的 get() 方法調用。

具體代碼對比

from collections import UserDict

class ADict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(key,[value]*2)


class BDict(UserDict):
    def __setitem__(self, key, value):
        super().__setitem__(key,[value]*2)

ad=ADict(name='jason')
print(ad) #{'name': 'jason'}
ad['age']=64
print(ad)  # {'name': 'jason', 'age': [64, 64]}
ad.update(job='student')
print(ad) # {'name': 'jason', 'age': [64, 64], 'job': 'student'}

bd=BDict(name='jason')
print(bd) # {'name': ['jason', 'jason']}
bd['age']=64
print(bd) # {'name': ['jason', 'jason'], 'age': [64, 64]}
bd.update(job='student')
print(bd) # {'name': ['jason', 'jason'], 'age': [64, 64], 'job': ['student', 'student']}

ADict和BDict的setitem方法是一樣的,把傳進來的value設置成列表形式,ADict繼承內置類型dict,BDict繼承自UserDict,
ADict類型的init和update函數不會發現用戶定義的setitem函數,而是繼續用dict的setitem函數,導致了value的值的類型不一致,有的是非列表有的是列表,這不是用戶願意看到的
BDict類型的init和update函數都用到了用戶定義的setitem函數,整個類實例的行爲看上去都是一致的

多重繼承和方法解析順序

python支持多重繼承
super()調用父類的方法會根據方法解析順序(MRO)的順序來調用方法
每個類都有一個內置屬性__mro__,是一個元祖,會按照MRO列出各個父類,調用方式是CLassName.__mro__,而不是類的實例
如果想調用特定的父類的方法,可以通過ParentClass.fun(child_instance),把子類的實例傳給父類的方法



class A():
    def fun(self):
        print("A fun of ",self)

class B(A):
    def fun(self):
        print("B fun of ",self)

class C(A):
    def fun(self):
        print("C fun of ",self)

class D(B,C):
    def fun(self):
        super().fun()

d=D()
d.fun() # B fun of  <__main__.D object at 0x00000286500AD438>
print("MRO of Class D ",D.__mro__)
# MRO of Class D  (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
C.fun(d) # C fun of  <__main__.D object at 0x0000020B7CA3D470>
A.fun(d) # A fun of  <__main__.D object at 0x000001FE08FED470>
發佈了53 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章