Python基礎系列講解——物件導向體系的概念剖析

mpsky發表於2021-09-09

關於Python的物件導向概念的介紹,網上已經多到了鋪天蓋地的程度,但是真正很系統化、結構化地把這個內容歸納清晰的卻不多,那麼偶然的機會看到了一幅關於描述Python物件導向機制的拓撲圖,結合這幅圖正好可以來說下Python物件導向的體系。

圖片描述

在拓撲圖中從左至右的框圖分別代表了元類、類/型別、例項,描述了物件導向體系中主要存在的兩種關係:實線描述的“父類”和“子類”關係;虛線描述的“類”和“例項”關係。“父類”和“子類”關係指的是子類繼承父類的特徵,同時“子類”還可以擁有自己的特徵。“類”和“例項”關係指的是“例項”物件是“類”物件的具體實現。比如蛇是一種爬行動物,其中蛇是子類,爬行動物是父類,蛇擁有爬行動物的特徵,同時又擁有標誌自己是一條蛇的特徵。這個機制的好處是可以在不改變超類程式碼的基礎上改變原有的功能。產生了所需的類後,我們可以透過類來建立例項,比如我有一條寵物蛇叫Squasher,那麼Squasher就是蛇的一個例項。

以內建型別list為例,我們發現list的型別是,list的“父類”或“超類”是(,),對於list的一個例項mylist,它的型別是,由於“抽象類”只能被繼承,不能被例項化,所以mylist並不存在“父類”或“超類”。同理,對於內建型別tuple、dict或int也是一樣。

print list.__class__ ——>>  
print list.__bases__ ——>>  (,)

mylist = [1,2,3]
print mylist.__class__ ——>>  
print mylist.__bases__ ——>>  AttributeError: 'list' object has no attribute '__bases__'

除了Python內建型別外,我們可以透過class語句繼承一個已存在的類/型別而新建一個新的類/型別,比如class C(object)繼承了“父類”或“超類”object,這裡要說明下的是Python 2.7 版本中C的型別為經典類classobj,如果C顯式繼承了超類’object’就成為了新式類,Python 3.x中所有的類都是新式類,即顯示或隱式繼承自object。

class C():pass
print(type(C)) ——>>  

class C(object):pass
print(type(C)) ——>>  

當我們需要創造一個全新的類時可以使用元類來實現,我們知道物件由類例項化得到的,而類也是物件,它也是由類例項化得到,元類的角色即為建立類的類,也就是透過例項化得到新的類,Python中只有type類及其子類才可以當元類。

那麼我們結合例子再來說下圖中’object’和’type’之間的關係。我們可以發現object是type的例項(用虛線連線),type本身也是自己的例項,同時object自己已經是所有物件的超類,包括也是type的超類(用實線連線),因此object並沒有超類。總體而言object和type是Python中的兩個源物件,它們互相依賴對方來定義,網上有人說雞生蛋和蛋生雞的關係倒也挺貼切的。

type(object) ——>>  
object.__class__  ——>> 
object.__bases__  ——>> ()
type.__class__ ——>>  
type.__bases__ ——>>  (,)

型別框圖中內建型別list與元類框圖中type之間的虛線箭頭連線又是怎麼回事呢?根據“虛線向下規則”(Dashed Arrow Down Rule,If B is an instance of M, and A is a subclass of B, then A is an instance of M as well.),由於object是type的例項,同時list、tuple、dict是object的子類,那麼list、tuple、dict也是type的例項(虛線所示)。另外一個“虛線向上規則”(Dashed Arrow Up Rule:If X is an instance of A, and A is a subclass of B, then X is an instance of B as well.)指的是mylist是list的例項,同時list又是object的子類,那麼mylist也是object的例項。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1806/viewspace-2814812/,如需轉載,請註明出處,否則將追究法律責任。

相關文章