首先要明白對象和引用的概念 (例子:a=1, a為引用,1為對象,對象1的引用計數器為1,b=1此時內存中只有一個對象1,a,b都為引用,對象的引用計數器此時為2,因為有兩個引用)
a=1,b=1
id(a)=id(b) #短的字符串,數字python在內存中是一個對象
a=[],b=[] id(a)!=id(b) #字典,數組這樣的對象在內存中python會new兩個不同的對象 a="new a string" b="new a string" #長的字符串python在內存中同樣會new兩個不同的對象 id(a)!=id(b)
引用計數器如何減少,當刪除該對象的引用時候該對象的引用計數器將會減少。
a=[1,2]
b= [a,a] #a對象的引用計數為2
del b[0] #a對象的引用計數變為1
#字典同理
a=1 {"a":a,"b":a} #a對象的引用計數為2 del b[b] #a對象的引用計數變為1
python的垃圾回收(3種)
引用計數
當對象的引用的計數器變為0的時候,該對象可能在內存中,但是已經不能訪問。python的垃圾回收時候不能做其他操作,如果一個對象的引用計數變為0的時候python就去回收該對象,那么很顯然Python的效率會很差,那什么時候python會來回收呢?這是一個好問題。
python會監聽自己new了多少個新的對象和有多少對象的引用計數器變為了,兩個數值做差的到的數和閾值去比較,大於閾值,內存開始進行垃圾回收,銷毀引用計數器為0的對象。
優點:簡單實時性,缺點:維護引用計數消耗資源,循環引用。
分代回收
為了提高效率,有很多對象,清理了很多次他依然存在,可以認為,這樣的對象不需要經常回收,可以把它分到不同的集合,每個集合回收的時間間隔不同。簡單的說這就是python的分代回收。
具體說一下,python中的垃圾分為1,2,3代,在1代里的對象每次回收都會去清理,當清理后有引用的對象依然存在,此時他會進入2代集合,同理2代集合清理的時候存在的對象會進入2代集合。
每個集合的清理時間如何分配,會先清理1代垃圾,當清理10次一代垃圾后會清理一次2代垃圾,當清理10次2代垃圾后會清理2代垃圾。
標記清除
按需分配,當內存不夠的時候,從寄存器和程序棧上的引用出發,遍歷對象,將遍歷的對象打上標記,然后在內存中清除沒有標記的對象。