Python記憶體管理機制

2022-08-28 17:18:20 字數 4551 閱讀 5708

關係圖如下:

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.垃圾 垃圾 機制 引用計數 標記清除 分帶 引用計數 引用計數也是一種垃圾收集機制,而且也是一種最直觀,最簡單的...