Python __del__()方法:銷毀對象


我們知道,Python 通過調用 __init__() 方法構造當前類的實例化對象,而本節要學的 __del__() 方法,功能正好和 __init__() 相反,其用來銷毀實例化對象。
事實上在編寫程序時,如果之前創建的類實例化對象后續不再使用,最好在適當位置手動將其銷毀,釋放其占用的內存空間(整個過程稱為垃圾回收(簡稱GC))。

大多數情況下,Python 開發者不需要手動進行垃圾回收,因為 Python 有自動的垃圾回收機制(下面會講),能自動將不需要使用的實例對象進行銷毀。

無論是手動銷毀,還是 Python 自動幫我們銷毀,都會調用 __del__() 方法。舉個例子:

class CLanguage:
    def __init__(self):
        print("調用 __init__() 方法構造對象")
    def __del__(self):
        print("調用__del__() 銷毀對象,釋放其空間")
clangs = CLanguage()
del clangs

程序運行結果為:

調用 __init__() 方法構造對象
調用__del__() 銷毀對象,釋放其空間

但是,讀者千萬不要誤認為,只要為該實例對象調用 __del__() 方法,該對象所占用的內存空間就會被釋放。舉個例子:

class CLanguage:
    def __init__(self):
        print("調用 __init__() 方法構造對象")
    def __del__(self):
        print("調用__del__() 銷毀對象,釋放其空間")
clangs = CLanguage()
#添加一個引用clangs對象的實例對象
cl = clangs
del clangs
print("***********")

程序運行結果為:

調用 __init__() 方法構造對象
***********
調用__del__() 銷毀對象,釋放其空間

注意,最后一行輸出信息,是程序執行即將結束時調用 __del__() 方法輸出的。

可以看到,當程序中有其它變量(比如這里的 cl)引用該實例對象時,即便手動調用 __del__() 方法,該方法也不會立即執行。這和 Python 的垃圾回收機制的實現有關。
Python 采用自動引用計數(簡稱 ARC)的方式實現垃圾回收機制。該方法的核心思想是:每個 Python 對象都會配置一個計數器,初始 Python 實例對象的計數器值都為 0,如果有變量引用該實例對象,其計數器的值會加 1,依次類推;反之,每當一個變量取消對該實例對象的引用,計數器會減 1。如果一個 Python 對象的的計數器值為 0,則表明沒有變量引用該 Python 對象,即證明程序不再需要它,此時 Python 就會自動調用 __del__() 方法將其回收。
以上面程序中的 clangs 為例,實際上構建 clangs 實例對象的過程分為 2 步,先使用 CLanguage() 調用該類中的 __init__() 方法構造出一個該類的對象(將其稱為 C,計數器為 0),並立即用 clangs 這個變量作為所建實例對象的引用( C 的計數器值 + 1)。在此基礎上,又有一個 clang 變量引用 clangs(其實相當於引用 CLanguage(),此時 C 的計數器再 +1 ),這時如果調用 del clangs語句,只會導致 C 的計數器減 1(值變為 1),因為 C 的計數器值不為 0,因此 C 不會被銷毀(不會執行 __del__() 方法)。
如果在上面程序結尾,添加如下語句:
del cl
print("-----------")

則程序的執行結果為:

調用 __init__() 方法構造對象
***********
調用__del__() 銷毀對象,釋放其空間
-----------

可以看到,當執行 del cl 語句時,其應用的對象實例對象 C 的計數器繼續 -1(變為 0),對於計數器為 0 的實例對象,Python 會自動將其視為垃圾進行回收。
需要額外說明的是,如果我們重寫子類的 __del__() 方法(父類為非 object 的類),則必須顯式調用父類的 __del__() 方法,這樣才能保證在回收子類對象時,其占用的資源(可能包含繼承自父類的部分資源)能被徹底釋放。為了說明這一點,這里舉一個反例:

class CLanguage:
    def __del__(self):
        print("調用父類 __del__() 方法")

class cl(CLanguage):
    def __del__(self):
        print("調用子類 __del__() 方法")
c = cl()
del c

程序運行結果為:

調用子類 __del__() 方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM