首先介紹一下python物件的記憶體模型,如下圖1所示:
圖1. pyobject物件記憶體模型
上圖可以看到,乙個pyobject必須包含ob_refcnt
和ob_type
這兩個屬性
。ob_refcnt
是這個物件的引用計數,而ob_type
則是指向_typeobject
結構體的指標,它是python內部的一種特殊物件,它是用來制定乙個物件型別的型別物件,所以上圖中它指向了乙個pytypeobject
。
在python中,物件機制的核心其實非常簡單,乙個是引用計數,乙個是型別資訊。
我們再來看定長物件none
,int
,list
,其結構如下圖2所示:
圖2.none
,int
,list
物件記憶體模型
上圖可以看到,none物件的記憶體模型是與pyobject一致的;而int物件則是多了乙個ob_ival
,這個字段其實就是儲存int真實的value。
問題一:令人奇怪的是,在python中,list其實是乙個可變長的,類似於c++中的vector的資料結構,為什麼它的記憶體模型是定長的呢?
其實它的記憶體模型的字段都是元資料(meta-data),而真正存放陣列資料的是ob_item
指向的乙個陣列。
問題二:在pylistobject
物件中,有乙個ob_size
,而在最後為什麼又有乙個allocated
,那麼這兩個變數之間的關係是什麼呢?
其實,ob_size
和allocated
都和pylistobject
物件的記憶體管理有關,pylistobject
所採用的記憶體管理策略和c++中的vector採取記憶體管理策略是一樣的。在每一次需要申請記憶體的時候,pylistobject
總會申請一大塊記憶體,這是申請的總記憶體的大小記錄在allocated
中,而實際被使用了的記憶體的數量則記錄在了ob_size
中。
我們再來看看變長物件的記憶體模型,例如tuple
,它的結構如下圖3所示:
圖3.tuple
物件記憶體模型
上圖就可以解釋,為什麼tuple在python中使用是乙個定長的list,為什麼在pyobject中卻是變長物件了。
而string的記憶體模型如下圖所示:
圖4.string
物件記憶體模型
在建立pystringobject
物件時,除了為pystring_object
申請記憶體,還有為字元陣列內的元素申請額外的記憶體(綠色填充的字元陣列記憶體)。然後將hash快取值設為-1,將引數str指向的字元陣列內的字元拷貝到pystringobject
所維護的空間中,在拷貝過程中,將字元陣列最後的'\0'
字元也拷貝了。
上面講述了很多python的基礎資料型別,而這些基礎型別(包括pytypeobject
)都是物件(all is object)。每個物件至少包含了ob_refcnt
和ob_type
兩個字段,如果是32bit的作業系統,那麼他們共是8個位元組。
型別記憶體模型(物件記憶體模型)
型別的記憶體模型的3個問題 1 包含什麼 附加資訊 2 怎麼布局 記憶體對齊 3 使用場景 怎麼使用附加資訊 除了包含結構型別的顯式成員變數外,型別記憶體模型需要解決附加資訊的引入問題 1 附加資訊 opaque 有哪些 型別資訊 函式資訊 繼承資訊 記憶體計數等 2 為什麼有附加資訊 1 解決多型...
物件記憶體模型
物件物件模型 物件在記憶體是如何存放的 存放規則 1.class記憶體對齊規則和struct相同。2.class 成員函式和成員變數分開存放,每個物件有獨享的成員變數 堆疊全域性資料 同一類的所有物件共享同一成員函式 段 3.呼叫成員函式時將物件位址傳遞給成員函式 隱式傳遞 成員函式通過物件位址 t...
python 記憶體模型
python 記憶體模型 1.python變數採用引用語義,每乙個變數名儲存的是實際存放資料的記憶體的位址 01.讀取資料時,x 10,可以認為,通過唯讀指標 位址 訪問資料10所在的記憶體空間,通過變數中存放的位址訪問記憶體只能讀,不能寫 02.寫,需要重新分配一塊記憶體空間,存放新資料,並用新位...