Python __del__方法:銷燬物件

lightwing發表於2021-09-11

Python __del__方法:銷燬物件

與 init() 方法對應的是 __del__() 方法,__init__() 方法用於初始化 Python 物件,而 __del__() 則用於銷燬 Python 物件,即在任何 Python 物件將要被系統回收之時,系統都會自動呼叫該物件的 __del__() 方法。

當程式不再需要一個 Python 物件時,系統必須把該物件所佔用的記憶體空間釋放出來,這個過程被稱為垃圾回收(GC,Garbage Collector),Python 會自動回收所有物件所佔用的記憶體空間,因此開發者無須關心物件垃圾回收的過程。

Python 採用自動引用計數(ARC)方式來回收物件所佔用的空間,當程式中有一個變數引用該 Python 物件時,
Python 會自動保證該物件引用計數為 1;當程式中有兩個變數引用該 Python 物件時,Python 會自動保證該物件引用計數為 2,
依此類推,如果一個物件的引用計數變成了 0,則說明程式中不再有變數引用該物件,表明程式不再需要該物件,
因此 Python 就會回收該物件。

大部分時候,Python 的 ARC 都能準確、高效地回收系統中的每個物件。但如果系統中出現迴圈引用的情況,比如物件 a 持有一個例項變數引用物件 b,而物件 b 又持有一個例項變數引用物件 a,此時兩個物件的引用計數都是 1,而實際上程式已經不再有變數引用它們,系統應該回收它們,此時 Python 的垃圾回收器就可能沒那麼快,要等專門的迴圈垃圾回收器(Cyclic Garbage Collector)來檢測並回收這種引用迴圈。

當一個物件被垃圾回收時,Python 就會自動呼叫該物件的 __del__ 方法。需要說明的是,不要以為對一個變數執行 del 操作,該變數所引用的物件就會被回收,只有當物件的引用計數變成 0 時,該物件才會被回收。因此,如果一個物件有多個變數引用它,那麼 del 其中一個變數是不會回收該物件的。

class Item:
    def __init__ (self, name, price):
        self.name = name
        self.price = price
    # 定義解構函式
    def __del__ (self):
        print('del刪除物件')
# 建立一個Item物件,將之賦給im變數
im = Item('滑鼠', 29.8)
x = im   # ①
# 列印im所引用的Item物件
del im
print('--------------')

程式中重寫了 Item 類的 __del__() 方法,該方法就是 Item 類的解構函式,當系統將要回收 Item 時,系統會自動呼叫 Item 物件的 __del__() 方法。

上面程式先建立了一個 Item 物件,並將該物件賦值給 im 變數,① 號程式碼又將 im 賦值給變數 x,這樣程式中有兩個變數引用 Item 物件,接下來程式執行 del im 程式碼刪除 im 物件,此時由於還有變數引用該 Item 物件,因此程式並不會回收 Item 物件。

執行上面程式,可以看到如下輸出結果:

--------------
del刪除物件

從上面程式的輸出結果可以看到,del im 執行之後,程式並沒有回收 Item 物件,只有等到程式執行將要結束時(系統必須回收所有物件),系統才會回收 Item 物件。

如果將程式中 ① 號程式碼註釋掉,再次執行上面程式,將會看到如下輸出結果:

del刪除物件
--------------

註釋掉 ① 號程式碼之後,當程式執行 del im 之後,此時程式中不再有任何變數引用該 Item 物件,因此係統會立即回收該物件,則無須等到程式結束之前。

後需要說明的是,如果父類提供了 __del__() 方法,則系統重寫 __del__() 方法時必須顯式呼叫父類的 __del__() 方法,這樣才能保證合理地回收父類例項的部分屬性。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3407/viewspace-2837274/,如需轉載,請註明出處,否則將追究法律責任。

相關文章