溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么

發(fā)布時(shí)間:2022-10-09 17:55:41 來(lái)源:億速云 閱讀:110 作者:iii 欄目:編程語(yǔ)言

本篇內(nèi)容介紹了“Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Python 中的 __del__ 魔法方法,也被稱為對(duì)象的終結(jié)者,是一個(gè)在對(duì)象即將被從內(nèi)存中移除之前被調(diào)用的方法。它實(shí)際上并不做從內(nèi)存中刪除對(duì)象的工作,我們將在后面看到它是如何發(fā)生的。相反,這個(gè)方法是用來(lái)做任何在對(duì)象被移除前需要發(fā)生的清理工作。例如,關(guān)閉對(duì)象在創(chuàng)建時(shí)打開(kāi)的任何文件。

在本節(jié)中,我們將使用下面這個(gè)類作為例子。

class MyNameClass:
    def __init__(self, name):
        self.name = name
    
    def __del__(self):
        print(f"Deleting {self.name}!")

登錄后復(fù)制

在上面的例子中,我們已經(jīng)定義了我們的類在初始化時(shí)接受一個(gè)名字的輸入,當(dāng)調(diào)用 finaliser 時(shí),它會(huì)通過(guò)打印相關(guān)實(shí)例的名字讓我們知道。這樣,我們就可以了解到哪些對(duì)象被從內(nèi)存中刪除,以及何時(shí)被刪除。

那么,CPython 什么時(shí)候會(huì)決定從內(nèi)存中刪除一個(gè)對(duì)象呢?有兩種方式(從CPython 3.10 開(kāi)始)會(huì)發(fā)生這種情況:引用計(jì)數(shù)和垃圾回收。

引用計(jì)數(shù)

如果我們?cè)?Python 中有一個(gè)指向某個(gè)對(duì)象的指針,那就是對(duì)該對(duì)象的引用。對(duì)于一個(gè)給定的對(duì)象 a ,CPython 會(huì)跟蹤有多少其他東西指向 a 。如果這個(gè)計(jì)數(shù)器達(dá)到零,就可以安全地從內(nèi)存中刪除這個(gè)對(duì)象,因?yàn)闆](méi)有其他東西在使用它。讓我們看一個(gè)例子。

>>> Harward = MyNameClass("Harward")
>>> del Harward
Deleting Harward!
>>>

登錄后復(fù)制

在這里,我們創(chuàng)建了一個(gè)新的對(duì)象(MyNamedClass("Harward")),并創(chuàng)建了一個(gè)指向它的指針(Harward =)。然后,當(dāng)我們刪除 Harwade 時(shí),我們刪除了這個(gè)引用,MyNamedClass 實(shí)例現(xiàn)在的引用計(jì)數(shù)為 0。 所以,CPython 決定從內(nèi)存中刪除它--而且,就在這之前,它的 __del__ 方法被調(diào)用,打印出了我們看到的上面的信息。

如果我們對(duì)一個(gè)對(duì)象創(chuàng)建了多個(gè)引用,我們將不得不擺脫所有的引用,以便使該對(duì)象被刪除。

>>> bob = MyNameClass("Bob")
>>> bob_two = bob # creating a new pointer to the same object
>>> del bob # this doesn't cause the object to be removed...
>>> del bob_two # ... but this does
Deleting Bob!

登錄后復(fù)制

當(dāng)然,我們的 MyNamedClass 實(shí)例本身可以包含指針--畢竟它們是任意的 Python 對(duì)象,我們可以給它們添加任何我們喜歡的屬性。讓我們看一個(gè)例子。

>>> jane = MyNamedClass("Jane")
>>> bob = MyNamedClass("Bob")
>>> jane.friend = bob # now the "Jane" object contains a pointer to the "Bob" object...
>>> bob.friend = jane

登錄后復(fù)制

我們?cè)谏厦娴拇a片斷中所做的是設(shè)置了一些循環(huán)引用。名字為 Jane 的對(duì)象包含一個(gè)指向名字為 Bob 的對(duì)象的指針,反之亦然。當(dāng)我們做下面的事情時(shí),情況就變得有趣了。

>>> del jane
>>> del bob

登錄后復(fù)制

我們現(xiàn)在已經(jīng)刪除了從命名空間到對(duì)象的指針。現(xiàn)在,我們完全不能訪問(wèn)那些 MyNameClass 對(duì)象了--但我們并沒(méi)有收到告訴我們它們即將被刪除的打印信息。這是因?yàn)檫@些對(duì)象仍有引用,包含在彼此之間,因此它們的引用計(jì)數(shù)不是 0 。

我們?cè)谶@里創(chuàng)建的是一個(gè)循環(huán)隔離體;在這個(gè)結(jié)構(gòu)中,每個(gè)對(duì)象在循環(huán)中至少有一個(gè)引用,使其保持活力,但循環(huán)中的所有對(duì)象都不能從命名空間中被訪問(wèn)。

循環(huán)隔離的直觀表現(xiàn)

下面是我們創(chuàng)建一個(gè)循環(huán)隔離時(shí)的直觀表現(xiàn)。

首先,我們創(chuàng)建兩個(gè)對(duì)象,每個(gè)對(duì)象在命名空間中都有一個(gè)名字。

Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么

接下來(lái),我們通過(guò)在每個(gè)對(duì)象上添加一個(gè)指針來(lái)連接我們的兩個(gè)對(duì)象。

Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么

最后,我們通過(guò)刪除兩個(gè)對(duì)象的原始名稱來(lái)從命名空間中刪除指針。在這一點(diǎn)上,這兩個(gè)對(duì)象從名字空間中是不可訪問(wèn)的,但每個(gè)對(duì)象都包含一個(gè)指向另一個(gè)對(duì)象的指針,所以它們的引用計(jì)數(shù)不是零。

Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么

所以,很明顯,引用計(jì)數(shù)本身并不足以保持運(yùn)行時(shí)的工作內(nèi)存中沒(méi)有無(wú)用的、不可回收的對(duì)象。這就是CPython的垃圾收集器發(fā)揮作用的地方。

“Python垃圾回收機(jī)制中的引用計(jì)數(shù)是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI