python垃圾回收機制
總概
python採用的是引用計數機制為主,標記-清除和分代收集兩種機制為輔的策略,在 Python 內部記錄著所有使用中的物件各有多少引用。
在C/C++中採用使用者自己管理維護記憶體的方式。自己管理記憶體極其自由,可以任意申請記憶體,但也為大量記憶體洩露、懸空指標等bug埋下隱患。
如何知道一個物件永遠都不能再使用了呢?很簡單,就是當這個物件的引用計數值為 0 時,說明這個物件永不再用,自然它就變成了垃圾,需要被回收。
計數表
a = 40 # 建立物件 <40>
b = a # 增加引用, <40> 的計數
c = [b] # 增加引用. <40> 的計數
del a # 減少引用 <40> 的計數
b = 100 # 減少引用 <40> 的計數
c[0] = -1 # 減少引用 <40> 的計數
示例
class Point:
def __init__( self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print class_name, "銷燬"
pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # 列印物件的id
del pt1
del pt2
del pt3
結果
3083401324 3083401324 3083401324
Point 銷燬
示例執行過程
執行過程:
1.建立Point物件:
pt1 = Point():建立了一個Point物件,其x和y屬性預設都是0。pt1是這個物件的第一個引用。
2.複製引用:
pt2 = pt1:pt2現在指向pt1所指向的同一個物件。
pt3 = pt1:同樣,pt3也指向pt1所指向的同一個物件。
3.列印物件的id:
print id(pt1), id(pt2), id(pt3):由於pt1、pt2和pt3都指向同一個物件,所以它們列印出的id是相同的。
4.刪除引用:
del pt1:刪除了pt1這個引用,但物件本身仍然存在,因為還有pt2和pt3指向它。
del pt2:同樣,刪除了pt2這個引用,但物件仍然因為pt3的引用而存在。
del pt3:最後,刪除了pt3這個引用。此時,沒有任何引用指向這個Point物件,Python的垃圾回收機制會識別到這個物件不再被使用,並銷燬它。
5.析構方法:
當Point物件被銷燬時,它的析構方法__del__會被呼叫。因此,在del pt3之後,會列印出"Point 銷燬"。
pt1 = Point():建立了一個Point物件,其x和y屬性預設都是0。pt1是這個物件的第一個引用。
2.複製引用:
pt2 = pt1:pt2現在指向pt1所指向的同一個物件。
pt3 = pt1:同樣,pt3也指向pt1所指向的同一個物件。
3.列印物件的id:
print id(pt1), id(pt2), id(pt3):由於pt1、pt2和pt3都指向同一個物件,所以它們列印出的id是相同的。
4.刪除引用:
del pt1:刪除了pt1這個引用,但物件本身仍然存在,因為還有pt2和pt3指向它。
del pt2:同樣,刪除了pt2這個引用,但物件仍然因為pt3的引用而存在。
del pt3:最後,刪除了pt3這個引用。此時,沒有任何引用指向這個Point物件,Python的垃圾回收機制會識別到這個物件不再被使用,並銷燬它。
5.析構方法:
當Point物件被銷燬時,它的析構方法__del__會被呼叫。因此,在del pt3之後,會列印出"Point 銷燬"。
此外
析構方法的呼叫時機是由Python的垃圾回收機制決定的,它可能在物件不再被引用後的某個不確定的時間點被呼叫。此外,對於簡單的物件,析構方法通常不是必需的,因為Python的記憶體管理已經足夠高效。析構方法主要用於釋放非記憶體資源,如檔案控制代碼、網路連線等。