關係圖如下:
2、物件,型別已知,每個物件都包含乙個頭部資訊(頭部資訊:型別識別符號和引用計數器)
注意
in [43]: a=456 #a的引用指向別的物件,重新賦值,a變數覆蓋了上面的a變數,所以a的記憶體位址發生改變
in [44]: id(a)
out[44]: 33166408
in [45]: id(b)
out[45]: 23242832
整數
in [46]: a=1
in [47]: b=1
in [48]: print(a is b)
true
字串
in [49]: c="good"
in [50]: d="good"
in [51]: print(c is d)
true
列表(不可變資料型別)
in [55]: g=
in [56]: h=
in [57]: print(g is h)
false
字典
dic =
dd=dic is dd
false
由執行結果可知:
1、python只快取了整數和字串(小資料池,**塊機制,請看我部落格,小資料池那章),因此每個物件在記憶體中只存有乙份,引用所指物件就是相同的,即使使用賦值語句,也只是創造新的引用,而不是物件本身;
2、python沒有快取列表,字典及其他物件,可以由多個相同的物件,可以使用賦值語句建立出新的物件。
1、普通引用
in [2]: import sys
in [3]: a=[1,2,3]
in [4]: getrefcount(a)
out[4]: 2
in [5]: b=a
in [6]: getrefcount(a)
out[6]: 3
in [7]: getrefcount(b)
out[7]: 3
注意:
當使用某個引用作為引數,傳遞給getrefcount()時,引數實際上建立了乙個臨時的引用。因此,getrefcount()所得到的結果,會比期望的多1。
2、容器物件
python的乙個容器物件(比如:表、詞典等),可以包含多個物件。
由上可見,實際上,容器物件中包含的並不是元素物件本身,是指向各個元素物件的引用。
3、引用計數增加
in [39]: getrefcount(123)
out[39]: 6
in [40]: n=123
in [41]: getrefcount(123)
out[41]: 7
in [42]: m=n
in [43]: getrefcount(123)
out[43]: 8
in [44]: a=[1,12,123]
in [45]: getrefcount(123)
out[45]: 9
4、引用計數減少1、物件的別名被顯式的銷毀
in [46]: del m
in [47]: getrefcount(123)
out[47]: 8
2、物件的乙個別名被賦值給其他物件
in [48]: n=456
in [49]: getrefcount(123)
out[49]: 7
3、物件從乙個視窗物件中移除,或,視窗物件本身被銷毀
in [50]: a.remove(123)
in [51]: a
out[51]: [1, 12]
in [52]: getrefcount(123)
out[52]: 6
4、乙個本地引用離開了它的作用域,比如上面的foo(x)函式結束時,x指向的物件引用減1。
當python中的物件越來越多,佔據越來越大的記憶體,啟動垃圾**(garbage collection),將沒用的物件清除。
1、原理
當python的某個物件的引用計數降為0時,說明沒有任何引用指向該物件,該物件就成為要被**的垃圾。比如某個新建物件,被分配給某個引用,物件的引用計數變為1。如果引用被刪除,物件的引用計數為0,那麼該物件就可以被垃圾**。
in [74]: a=[321,123]
in [75]: del a
2、解析del
del a後,已經沒有任何引用指向之前建立的[321,123],該錶引用計數變為0,使用者不可能通過任何方式接觸或者動用這個物件,當垃圾**啟動時,python掃瞄到這個引用計數為0的物件,就將它所佔據的記憶體清空。
3、注意
1、垃圾**時,python不能進行其它的任務,頻繁的垃圾**將大大降低python的工作效率;
2、python只會在特定條件下,自動啟動垃圾**(垃圾物件少就沒必要**)
3、當python執行時,會記錄其中分配物件(object allocation)和取消分配物件(object deallocation)的次數。當兩者的差值高於某個閾值時,垃圾**才會啟動。
in [93]: import gc
in [94]: gc.get_threshold() #gc模組中檢視閾值的方法
out[94]: (700, 10, 10)
閾值分析:
700即是垃圾**啟動的閾值;
每10次0代垃圾**,會配合1次1代的垃圾**;而每10次1代的垃圾**,才會有1次的2代垃圾**;
當然也是可以手動啟動垃圾**:
in [95]: gc.collect() #手動啟動垃圾**
out[95]: 2
4、何為分代**
python將所有的物件分為0,1,2三代;
所有的新建物件都是0代物件;
當某一代物件經歷過垃圾**,依然存活,就被歸入下一代物件。
四、記憶體池機制
python中有分為大記憶體和小記憶體:(256k為界限分大小記憶體)
1、大記憶體使用malloc進行分配
2、小記憶體使用記憶體池進行分配
3、python的記憶體池(金字塔)
第3層:最上層,使用者對python物件的直接操作
第1層和第2層:記憶體池,有python的介面函式pymem_malloc實現-----若請求分配的內存在1~256位元組之間就使用記憶體池管理系統進行分配,使用pymalloc實現的分配器進行分配記憶體,但是每次只會分配一塊大小為256k的大塊記憶體,不會呼叫free函式釋放記憶體,將該記憶體塊留在記憶體池中以便下次使用。
第0層:大記憶體-----若請求分配的記憶體大於256k,則使用系統的 malloc函式分配記憶體,free函式釋放記憶體。
第-1,-2層:作業系統進行操作
Python記憶體管理機制
一 python記憶體 因為要呼叫while迴圈,迴圈內有temp變數,不清楚python是否會在每一輪迴圈結束後自動釋放temp記憶體空間,做了乙個記憶體測試,發現無論temp none,還是del temp,只能銷毀變數,無法完全釋放記憶體空間。注 紅色部分標出相同記憶體id。python vi...
python記憶體管理機制
a 1整數1為乙個物件。而a是乙個引用。利用賦值語句,引用a指向物件1。在python中,整數和短小的字元,python都會快取這些物件,以便重複使用。當我們建立多個等於1的引用時,實際上是讓所有這些引用指向同乙個物件。a 1 b 1 print id a print id b 在python中,每...
python記憶體管理機制
1.引用計數 當乙個python物件被引用時 其引用計數增加 1 當其不再被變數引用時 引用計數減 1 當物件引用計數等於 0 時,物件被刪除 引用計數是一種非常高效的記憶體管理機制 2.垃圾 垃圾 機制 引用計數 標記清除 分帶 引用計數 引用計數也是一種垃圾收集機制,而且也是一種最直觀,最簡單的...