Python中繼承的優缺點

2021-09-14 03:20:36 字數 3199 閱讀 2932

1、不要試圖在內建型別的子類中重寫方法,可以繼承collections的可拓展類尋求變通;

2、掌握多重繼承中的mro和super;

3、了解處理多重繼承的一些建議。

1、內建型別的方法不會呼叫子類覆蓋的方法

內建類可以子類化,但是內建型別的方法不會呼叫子類覆蓋的方法。下面以繼承dict的自定義子類重寫__setitem__為例說明:

class modifieddict(dict):

def __setitem__(self, key, value):

super().__setitem__(key,[value]*2)

a=modifieddict(one=1)

a["two"]=2

print(a)

a.update(three=3)

print(a)#輸出

從輸出可以看到,鍵值對one=1和three=3存入a時均呼叫了dict的__setitem__,只有運算子會呼叫我們預先覆蓋的方法。

問題的解決方式在於不去子類化dict,而是子類化colections.userdict。

2、子類化collections中的類

使用者自定義的類應該繼承collections模組,如userdict,userlist,userstring。這些類做了特殊設計,因此易於拓展。子類化userdict的**如下:

from collections import userdict

class modifieddict(userdict):

def __setitem__(self, key, value):

super().__setitem__(key,[value]*2)

b=modifieddict(one=1)

b["two"]=2

b.update(three=3)

print(b)#輸出

1、方法解析順序(method resolution order,mro)

在多重繼承中存在不相關的祖先類實現同名方法引起的衝突問題,這種問題稱作「菱形問題」。python依靠特定的順序遍歷繼承圖,這個順序叫做方法解析順序。如圖,左圖是類的uml圖,右圖中的虛線箭頭是方法解析順序。

提到類的屬性__mro__,就會提到super:

super 是個類,既不是關鍵字也不是函式等其他資料結構。
作用:super是子類用來呼叫父類方法的。

語法:super(a_type, obj);

a_type是obj的__mro__,當然也可以是__mro__的一部分,同時issubclass(obj,a_type)==true

舉個例子, 有個 mro: [a, b, c, d, e, object]

我們這樣呼叫:super(c, a).foo()

super 只會從 c 之後查詢,即: 只會在 d 或 e 或 object 中查詢 foo 方法。

下面構造乙個菱形問題的多重繼承來深化理解:

class a:

def ping(self):

print("a-ping:",self)

class b(a):

def pong(self):

print("b-pong:",self)

class c(a):

def pong(self):

print("c-pong:",self)

class d(b, c):

def ping(self):

print("d-ping:",self)

super().ping()

def pingpong(self):

self.ping()

super().ping()

self.pong()

super(b,d).pong(self)

d=d()

d.pingpong()

print(d.mro())

輸出如下:

d-ping: <__main__.d object at>

a-ping: <__main__.d object at>#前兩行對應self.ping()。

a-ping: <__main__.d object at>#此處super呼叫父類的ping方法。

b-pong: <__main__.d object at>

c-pong: <__main__.d object at>#此處從b之後搜尋父類的pong()

[, , , , ]#類d的__mro__,資料以元組的形式儲存。

分析:d.pingpong()執行super.ping(),super按照mro查詢父類的ping方法,查詢在類b到ping之後輸出了b.ping()。

3、處理多重繼承的建議

(1)把介面繼承和實現繼承區分開;

(2)使用抽象基類顯式表示介面;

(3)通過混入重用**;

混入類為多個不相關的子類提供方法實現,便於重用,但不會例項化。並且具體類不能只繼承混入類。

(4)在名稱中明確指明混入;

python中沒有把類宣告為混入的正規方式,luciano推薦在名稱中加入mixin字尾。如tkinter中的xview應變成xviewmixin。

(5)抽象基類可以作為混入,反過來則不成立;

抽象基類與混入的異同:

(6)不要子類化多個具體類;

具體類可以沒有,或者至多乙個具體超類。

例如,class dish(china,japan,tofu)中,如果tofu是具體類,那麼china和japan必須是抽象基類或混入。

(7)為使用者提供聚合類;

聚合類是指乙個類的結構主要繼承自混入,自身沒有新增結構或行為。tkinter採納了此條建議。

(8)優先使用物件組合,而不是類繼承。

優先使用組合可以令設計更靈活。

組合和委託可以代替混入,但不能取代介面繼承去定義型別層次結構。

流暢的Python 繼承的優缺點

1.子類化內建型別很麻煩 在python3中,內建型別可以子類化,但是有個重要的注意事項 內建型別 cpython 不會呼叫使用者定義的類覆蓋的特殊方法。內建型別的方法不會呼叫子類覆蓋的方法。例如,dict 的子類覆蓋的 getitem 方法不會被內建型別的get 方法呼叫。class doppel...

組合 繼承的優缺點

組合的優點和缺點 n 優點 f 容器類僅能通過被包含物件的介面來對其進行訪問。f 黑盒 復用,因為被包含物件的內部細節對外是不可見。f 對裝性好。f 實現上的相互依賴性比較小。譯者注 被包含物件與容器物件之間的依賴關係比較少 f 每乙個類只專注於一項任務。f 通過獲取指向其它的具有相同型別的物件引用...

Python的優缺點

python是著名的 龜叔 guido van rossum在1989年聖誕節期間,為了打發無聊的聖誕節而編寫的乙個程式語言。最後說說python的缺點。任何程式語言都有缺點,python也不例外。優點說過了,那python有哪些缺點呢?第乙個缺點就是執行速度慢,和c程式相比非常慢,因為python...