前言
①python通過調用 __init__() 方法構造目前類的執行個體化對象。【建立對象時,python解釋器預設調用 __init__() 方法】
② __del__() 方法的功能正好與 __init__() 方法相反,其用來銷毀執行個體化對象。【删除一個對象時,python解釋器預設調用 __del__() 方法】
③事實上在編寫程式時,如果之前建立的類執行個體化對象後續不再使用,最好在适當位置手動将其銷毀,釋放其占用的記憶體空間(整個過程稱為垃圾回收(簡稱GC))。
④大多數情況下,Python 開發者不需要手動進行垃圾回收,因為 Python 有自動的垃圾回收機制,能自動将不需要使用的執行個體對象進行銷毀。
執行個體講解
__del__() :
使用場景:
1、當删除對象時,Python解析器會預設調用 __del__() 方法,即對象引用執行完後python會自動調用 __del__() 方法。
2、銷毀(釋放)記憶體中的對象時回調 __del__() 方法。
執行個體一:
class CLanguage:
def __init__(self):
print("調用 __init__() 方法構造對象")
def __del__(self):
print("調用__del__() 銷毀對象,釋放其空間")
clangs = CLanguage()
del clangs
運作結果:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SMwYTO1QmN0UWOyATNmJWYyYzX2ATOyETM3EzLcZDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
【注意1】:不能誤認為,隻要該執行個體對象調用 __del__() ,該執行個體對象所占用的記憶體空間就會被釋放。
比如:
class CLanguage:
def __init__(self):
print("調用 __init__() 方法構造對象")
def __del__(self):
print("調用__del__() 銷毀對象,釋放其空間")
clangs = CLanguage()
# 添加一個引用clangs對象的執行個體對象
cl = clangs
del clangs # 删除執行個體對象(實際上是對執行個體對象的引用計數減1)
print("***********")
運作結果:上述代碼最後一行輸出資訊,是程式執行即将結束時調用 __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)。在此基礎上,又有一個 cl變量引用 clangs(其實相當于引用 CLanguage(),此時 C 的計數器再 +1 ),這時如果調用 del clangs 語句,隻會導緻 C 的計數器減 1(值變為 1),因為 C 的計數器值不為 0,是以 C 不會被銷毀(不會執行 __del__() 方法)。
④再次舉例:當執行 del cl 語句時,其應用的對象執行個體對象 C 的計數器繼續 -1(變為 0),對于計數器為 0 的執行個體對象,Python 會自動将其視為垃圾進行回收。
class CLanguage:
def __init__(self):
print("調用 __init__() 方法構造對象")
def __del__(self):
print("調用__del__() 銷毀對象,釋放其空間")
clangs = CLanguage()
# 添加一個引用clangs對象的執行個體對象
cl = clangs
del clangs # 删除執行個體對象(實際上是對執行個體對象的引用計數減1)
print("***********")
del cl # 删除執行個體對象(實際上是對執行個體對象的引用計數再減1)
print("-----------")
運作結果:
執行個體二:
class User:
def __init__(self, username):
self.user = username
print('User 初始化成功---')
def get_info(self):
print(self.user)
def __del__(self):
print('User 對象被回收---')
if __name__ == '__main__':
# 建立一個user對象
u = User(username='XXX')
# 删除該User對象
del u
print('del u -------------')
運作結果:
代碼詳解:
u = User() 在記憶體中建立了一個 User 對象,并且讓變量 u 引用記憶體中的 User 對象。
del u 删除變量 u , 此時記憶體中的 User 對象沒有任何變量對其引用,Python解析器就會回調 __del__() 方法,回收記憶體。
執行個體三:
class User:
def __init__(self, username):
self.user = username
print('User 初始化成功---')
def get_info(self):
print(self.user)
def __del__(self):
print('User 對象被回收---')
if __name__ == '__main__':
u1 = User('XXX')
u2 = u1
del u1
print('del u1 -------')
del u2
print('del u2 -------')
運作結果:
代碼解析:
u1 = User() 建立一塊存放 User 對象的記憶體,并且,變量 u1 指向該記憶體。
u2 = u1 此處又建立變量 u2, 并且 u2 引用了 u1 的記憶體位址,此時,u1 和 u2 同時引用同一個記憶體位址。
del u1 删除 u1 時,删除該變量對User對象的引用,此時,由于記憶體中的 User 對象還在被 u2 引用,是以不會回收該記憶體(不會回調 __del__() 方法)。
del u2 删除 u2 後,記憶體中的 User 對象已經沒有引用的變量,此時解釋器才會對記憶體進行回收,回調 __del__() 方法。
執行個體四:當執行個體對象的引用計數為0時,python解釋器會自動調用 __del__() 銷毀對象,回收記憶體空間。
class User:
def __init__(self, username):
self.user = username
print('User 初始化成功---')
def get_info(self):
print(self.user)
def __del__(self):
print('User 對象被回收---')
if __name__ == '__main__':
User('XXX').get_info()