Python記憶體管理機制

2022-07-31 19:06:11 字數 4371 閱讀 9376

由於python中萬物皆物件,所以python的儲存問題是物件的儲存問題,並且對於每個物件,python會分配一塊記憶體空間去儲存它

注意:

變數名沒有型別,型別屬於物件(因為變數引用物件,所以型別隨物件),變數引用什麼型別的物件,變數就是什麼型別的。

a = 123

b = a

print(id(a))

print(id(b))

a = 456

print(id(a))

print(id(b))

通過is進行引用所指判斷,is是用來判斷兩個引用所指的物件是否相同

整數:

a = 1

b = 1

print(a is b) # true

短字串:

c = "good"

d = "good"

print(c is d) # true

長字串:

e = "very good"

f = "very good"

print(e is f) # false

列表:

g = 

h =

print(g is h) # false

由執行結果可知:python快取了整數和短字串,因此每個物件在記憶體中只存有乙份,引用所指物件就是相同的,即使使用賦值語句,也只是創造新的引用,而不是物件本身;

python沒有快取長字串、列表及其他物件,可以由多個相同的物件,可以使用賦值語句建立出新的物件。

在python中,每個物件都有指向該物件的引用總數---引用計數

檢視物件的引用計數:sys.getrefcount()

import sys

a = [1, 2, 3]

print(sys.getrefcount(a)) # 2

b = 2

print(sys.getrefcount(a)) # 3

print(sys.getrefcount(b)) # 3

注意:當使用某個引用作為引數,傳遞給getrefcount()時,引數實際上建立了乙個臨時的引用。getrefcount()所得到的結果,會比期望的多1。

python的乙個容器物件(比如:表、詞典等),可以包含多個物件

由上可見,實際上,容器物件,如列表、元組、字典等,儲存的其它物件,僅僅是對其它物件的引用,即位址,並不是這些物件本身

物件被建立,引用計數增加1

物件被引用,增加1

作為容器的物件,增加1

物件被當作引數傳入函式func(object),增加2

import sys

# 物件被建立

obj = "i love python, i want to be a good programmer!"

print(sys.getrefcount(obj) - 1) # 3

# 被引用

m = obj

print(sys.getrefcount(obj) - 1) # 4

p = m

print(sys.getrefcount(obj) - 1) # 5

# 作為容器物件的乙個元素

a = ["a", "b", obj]

print(sys.getrefcount(obj) - 1) # 6

def foo(x):

z = "hello world! "

print(sys.getrefcount(obj) - 1) # 8

print(z)

foo(obj)

print(sys.getrefcount(obj) - 1) # 6 函式執行完畢後區域性命名空間被銷毀,引用計數減少

物件的別名被顯式減少del obj物件的乙個別名被賦值給其它物件

物件從乙個容器物件中移除,或,容器物件本身被銷毀

乙個本地引用離開了它的作用域,比如上面的foo(x)函式結束時,x指向的物件引用減1

作用:

當python中的物件越來越多,佔據越來越大的記憶體,啟動垃圾**garbage collection,將沒用的物件清除

作用:

垃圾**檢測流程:

如何找到迴圈引用並釋放記憶體:

收集所有容器物件(迴圈引用只針對容器物件,其它物件不會產生迴圈引用),使用雙向鍊錶(可以看作乙個集合)對這些容器物件進行引用

針對每乙個容器物件,使用變數gc_refs來記錄當前對應的引用個數

針對每乙個容器物件,找到其正在引用的其它容器物件,並將這個被引用的容器物件引用計數減去1

檢查所有容器物件的引用計數,若為0,則證明該容器物件是由於迴圈引用存活下來的,並對其進行銷毀

提公升查詢迴圈引用的效能:

分代**機制:

預設乙個物件被建立出來後,屬於0代

如果經歷過這一代「垃圾**」後,依然存活,則劃分為下一代

「垃圾**」的週期順序為

0代「垃圾**」一定次數,會觸發0代和1代**

1代「垃圾**」一定次數,會觸發0代,1代和2代**

通過這個分代**機制,迴圈引用處理過程就會得到很大的效能提公升

自動**:

手動**:這裡要使用gc模組中的collect()方法,使得執行這個方法時執行分代**機制

import objgraph, gc, sys  # objgraph模組的count()方法是記錄當前類產生的例項物件的個數

class person(object):

pass

class dog(object):

pass

p = person()

d = dog()

print(sys.getrefcount(p) - 1, sys.getrefcount(d) - 1) # 1, 1

p.pet = d

d.master = p

print(sys.getrefcount(p) - 1, sys.getrefcount(d) - 1) # 2, 2

del p, d

print(objgraph.count("person"), objgraph.count("dog")) # 1, 1

gc.collect()

print(objgraph.count("person"), objgraph.count("dog")) # 0, 0

python中有分為大記憶體和小記憶體:(256k為界限分大小記憶體)

大記憶體使用malloc進行分配

小記憶體使用記憶體池進行分配

python的記憶體(金字塔):

python的記憶體管理機制就是引用計數器機制和垃圾**機制的混合機制

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