在Python的學習中咱們確定會聽到一句話:「python中一切皆對象」。python
若是再接着學習下去的話,咱們就會接觸到Python中的type, object, class等概念。網上也有很多文章闡述了這三者之間的關係,可是在看了大部分文章以後我仍是似懂非懂,感受就像有什麼東西卡在了喉嚨一直嚥下不去同樣。web
因而爲了能讓本身晚上順利吃上飯,我立馬對着搜索引擎就是一頓操做,終於趕在外賣小哥打響我電話以前,嚥下了這幾個如鯁在喉的概念,舒服!
趁着外賣小哥上樓這會,分享下我學習研究後的理解吧。算法
python做爲面向對象的語言之一,符合一切基於面向對象理念的設計。在面向對象的體系中,對象存在着兩種關係。後端
簡單來講即子類繼承於父類,子類擁有其自身及父類的方法和屬性,同名的子類方法和屬性將會覆蓋父類的方法和屬性。
語義化的理解栗子爲:「蛇」類繼承自「爬行動物類」,因此「蛇是一種爬行動物」,英文說「snake is a kind of reptile」。
在python中的繼承關係能夠簡單表示以下:數據結構
class Reptile:
title = '爬行動物'
def crawl(self):
print(self.title)
class Snake(Reptile):
def crawl_a(self):
print(self.title)
p = Snake()
p.crawl() # 爬行動物
p.crawl_a() # 爬行動物
print(p.title) # 爬行動物
複製代碼
上面這個栗子中,子類Snake繼承了父類Reptile的title屬性和crawl方法,使得類B的實例對象b能調用父類的a屬性和get方法。
另外,若是要查看一個類(class)的父類,可使用class_name.__bases__
的形式來查看。app
Snake.__bases__ # (<class '__main__.Reptile'>,)
複製代碼
若是繼承關係比如父與子的關係,實例化關係則是一個從抽象到具體的過程。實例是某個類中具體的個體的表示。
語義化的理解栗子爲:「小p是一條蛇」,「蛇」是一個分類,「小p」則是這個分類中的一個具體的個體。英文說「小p is an instance of snake」。學習
class Snake:
pass
p = Snake() # p是Snake類的實例對象
複製代碼
若是想要查看一個對象是由哪一個類實例化而來,可使用type()
或 object_name.__class__
來查看。表示對象屬於什麼類型。搜索引擎
type(p) # <class '__main__.Snake'> 表示對象p是由類Snake實例化而來,p的類型是Snake
p.__class__ # <class '__main__.Snake'> 表示對象p是由類Snake實例化而來,p的類型是Snake
複製代碼
有了以上的基礎,咱們就能夠一步一步來探究python中對象潛藏着一些祕密了。嘿嘿嘿~ spa
先看看下面樸而不素的代碼:.net
class A:
pass
a = A()
print(A.__bases__) # (<class 'object'>,)
print(object.__bases__) # ()
print(type(a)) # <class '__main__.A'>
print(type(A)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type.__bases__) # (<class 'object'>,)
複製代碼
經過上面的很簡單的代碼,運用一眼洞穿法
,咱們能夠根據每一個打印語句的結果獲得一些簡單的觀察結論:
A
實例化而來,a的類型爲A
,這個比較容易理解。type
這個類實例化而來,類A的類型爲type
,說明類A是一個類的同時也是一個對象(類A是類type的實例化對象)。這裏可能有點暈可是請先接着看下去吧。object
這個頂端類也是由type
這個類實例化而來,類object
的類型也爲type
,也說明object做爲一個類的同時也是一個對象。看完上面的這些觀察結論,相信有一部分童鞋已經兩眼發懵了,什麼類A是一個類也是一個對象,object類的類型是type,而type類的父類又是object…blablabla
誒,莫方莫方,俗話說無圖言*,這裏先來一張圖簡單表示一下這幾者的關係,舒緩一下情緒:
下面咱們就能夠開始看圖寫做文啦~
藍色箭頭由實例對象指向實例化它的類,紅色箭頭由子類指向父類。值得注意的是,這個圖有幾個關鍵的地方:
有了以上的鋪墊,咱們能夠知道一個最普通的實例對象鏈是這樣子的: type --實例化--> object --衍生--> class --實例化--> a(具體對象)
這部分都是比較好理解的,但關鍵的問題是 ———— object類做爲type類的父類,怎麼會是由type類實例化出來的?還有type類竟然是由type本身實例化出來的?這都是什麼操做?
我的認爲,這兩個問題解決了才能更好地理解type、class、object三者的關係。然而要知道爲何python是這樣設計的,最好的作法即是去翻他們的源碼啦。不過在翻以前,其實已經有一些大佬對python的源碼作了解讀,經過搜索引擎認真找尋即可找到想要的答案。python的底層是C的實現,下面的源碼若是看不懂的話請別在乎,由於不妨礙理解。
(⊙o⊙)
咱們能夠看看在源碼中,type
類和object
類分別是什麼:type
類其實是:
#define PyVarObject_HEAD_INIT(type, size)
1, type, size,
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
0, /* tp_base */
...
}
複製代碼
object
類其實是:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
sizeof(PyObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_base */
...
}
複製代碼
這兩個類結構體中的各項的具體含義這裏不作深究,由於不在本文研究範圍內。咱們只須要關注這兩個結構中的第一行:
PyVarObject_HEAD_INIT(&PyType_Type, 0)
它表示這個類結構的對象類型。能看出來object
類 和 type
類的對象類型都是 &PyType_Type
,而 PyType_Type
正是底層表示type類的結構體!
這兩個結構體就說明了:object
類將類型(即誰實例化了這個類)設置成了type
類,type
類將類型設置成了本身!這實際上是python底層實現的一個小小的trick~
而後在type
類的初始化過程當中,執行了以下代碼:
type->tp_base = &PyBaseObject_Type;
複製代碼
轉換成python爲
type.__base__ = (object,)
複製代碼
表示將object類指定爲type類的父類,這不就是第二個問題的答案所在嗎?
源碼看到這裏,前面的兩個問題就已經所有解決了,咱們能夠開始全面總結一下type,class,object的關係了。
type,class,object三者關係:
寫到這裏,python中這三者的關係探究就差很少了,只能說技術寫做不是一件容易的事情,先後改了很多東西仍是不那麼讓本身滿意,可是已經按照本身的意思給表述出來了,但願以後能寫得更順手一些。話說外賣小哥已經在門口等了我5分鐘了,寫文章死了那麼多腦細胞,胃口必定不錯吧哈哈。
若是你以爲這篇內容對你有幫助,我想邀請你幫我三個小忙: