Python萬物皆對象理解及源碼學習
萬物皆對象
這篇博客的內容主要是針對Python中萬物皆對象的理解,對Python的類型、對象體系做一個整體的梳理。
在Python中,一切皆為對象,一個整數是一個對象,一個字符串也是一個對象,基本類型(如int)也是對象。Python不再區別對待基本類型和對象,所有的基本類型內部均由對象實現。
>>> a = int >>> b = 1 >>> id(a) 140734789683952 >>> id(int) 140734789683952 >>> a <class 'int'> >>> id(b) 2421963817200 >>> id(1) 2421963817200 >>> b 1
1 類型對象和實例對象
Python中的類型是一種對象,稱為類型對象。整數類型、字符串類型,以及我們通過class關鍵字定義的自定義類型也是一個對象。
通過類實例化可以得到一個實例化對象,稱為實例對象
2 類型、對象體系
2.1 元類型type
前面我們提到:Python中的類型是一種對象,稱為類型對象。那麼類型對象的類型又是什麼呢?
>>> type(int) <class 'type'> >>> int.__class__ <class 'type'>
可以看到,類型的類型是type,我們稱之為元類型,但是這個類型比較特殊,它的實例對象是類型對象。此外,Python中還有一個特殊的類型object,所有其他類型都繼承於object,即object是所有類型的基類。
圖示如下:
2.2 自定義類型
除瞭Python的內置類型,我們自定義一個類型MyClass,同樣地,可以得到:
2.3 自定義類型子類
再定義一個類型MySubClass,該類型為MyClass的子類:
2.4 type和object的關系
在上述示例中,我們描述瞭不同對象、類型之間的繼承、類型關系,但是對於兩個特殊的類型type和object的關系並沒有指出,我們先來打印看一下:
>>> type(type) <class 'type'> >>> type(object) <class 'type'> >>> type.__base__ <class 'object'> >>> object.__base__ >>> print(object.__base__) None
可以看到:object的類型也是type,type本身的類型也是type;而type的父類也是所有對象的父類——object,而object本身沒有父類。由此我們可以歸納出:
object是所有類型的基類(除瞭它自己),本質上是一種類型,其類型是type,同時也是type的基類;
type是所有類型的類型,本質上是一種類型,其類型是它自己,也是object的類型;
註:object本身不能有基類,這是因為——對於存在繼承關系的類,成員屬性和成員方法查找需要回溯繼承鏈,不斷查找基類。因此,繼承鏈必須有一個終點,不然就會死循環。
最後我們把type和object的關系補充進來:
3 可變對象與不可變對象
可變對象在創建之後,其值可以修改;不可變對象在創建之後,其值不可以進行修改。
以Python中的整數對象為例:整數類型是不可變類型,整數對象是不可變對象。“修改整數對象”時,Python將以新值創建一個新對象,變量名與新對象進行綁定,舊對象如果沒有其他引用,則會被釋放(通過“小整數池”進行創建回收優化,具體後續介紹,這裡先按下不表,後續會補充)。
圖示如下:
以Python中的列表對象為例:列表類型是可變類型,列表對象是可變對象。列表對象內部會維護一個動態數組,存儲元素對象的指針,列表對象再增減對象的時候,會修改該數組,而列表對象的“頭部”(後續會詳細介紹)會保持不變:
4 變長對象和定長對象
定長對象:對象的內存大小一定
邊長對象:同一類型,不同對象會有不同的大小
通過sys.getsizeof()可以查看一個對象的大小:
>>> import sys >>> a = 1 >>> b = 1111111111111111111111111111111111111111111111111111111111 >>> c = 1.0 >>> d = 1.00000000000000000000000000000000000000000000000000000001 >>> sys.getsizeof(a) 28 >>> sys.getsizeof(b) 52 >>> sys.getsizeof(c) 24 >>> sys.getsizeof(d) 24
整數對象是變長對象:固定位數的整數能夠表示的范圍是有限的,故整數對象會隨著自身的數值大小而改變自身內存大小。在Python中采用瞭類似C++中大整數類的思路實現整數對象,通過串聯多個普通32位整數來支持更大的數值范圍(詳細源碼後續介紹)。
浮點數對象是定長對象:根據機組的知識,我們用32位表示單精度浮點數,用64位表示雙精度浮點數,它們都是定長的。在Python中,浮點數背後是由一個double來實現的,就算表示很大的數,浮點數對象的大小也不變(這樣做的代價是犧牲瞭精度)。當然,浮點數也是有大小限制的,可以思考下:我們通過float()將一個很大的int轉化為float時,是否會報錯?Python底層是否做瞭相應的判斷呢?
5 補充
變量名:我們創建對象時會為對象分配對應的內存空間,那麼我們將變量名和對象綁定時,變量又是如何存儲的呢?
詳見Python源碼學習筆記:Python作用域與名字空間
以上就是Python萬物皆對象理解及源碼學習的詳細內容,更多關於Python對象的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- python 中sys.getsizeof的用法說明
- Python對象的底層實現源碼學習
- python 進制轉換 int、bin、oct、hex的原理
- Python黑魔法之metaclass詳情
- python中super()函數的理解與基本使用