對(duì) weakref 的一點(diǎn)理解

class Node(object):

    def __init__(self, data):
        self.data = data
        self.parent = None
        self.children = []

    def add_child(self, child):
        self.children.append(child)
        child.parent = self

    def __del__(self):
        print '__del__'


n = Node(0)
del n
# __del__
n1 = Node(1)
n2 = Node(2)
n1.add_child(n2)
del n1 # no output
n2.parent
# <__main__.Node at 0x7fd87ad5c250>

雙親節(jié)點(diǎn)的指針指向孩子節(jié)點(diǎn),孩子節(jié)點(diǎn)又指向雙親節(jié)點(diǎn)。這構(gòu)成了循環(huán)引用,所以每個(gè)對(duì)象的引用計(jì)數(shù)都不可能變成 0

我們可以手動(dòng)使用 gc 模塊來(lái)進(jìn)行垃圾回收

import gc

gc.collect()

糟糕的是,我們這里循環(huán)引用的對(duì)象都實(shí)現(xiàn)了 __del__ 方法,gc 模塊不會(huì)銷毀這些對(duì)象,因?yàn)?gc 模塊不知道應(yīng)該先調(diào)用哪個(gè)對(duì)象的 __del__ 方法。gc模塊會(huì)把這樣的對(duì)象放到 gc.garbage 中,并不會(huì)銷毀對(duì)象。

n1 = Node(1)
n2 = Node(2)
print n1, n2
# <__main__.Node object at 0x7f94109906d0> <__main__.Node object at 0x7f9410990610>
n1.add_child(n2)
del n1
del n2
gc.collect()
# 64
gc.garbage
# [<__main__.Node object at 0x7f94109906d0> <__main__.Node object at 0x7f9410990610>]

我們可以通過(guò) weakref 來(lái)解決,如果一個(gè)對(duì)象只剩下一個(gè)弱引用,那么它是可以被垃圾回收的

import weakref


class Node(object):

    def __init__(self, data):
        self.data = data
        self._parent = None
        self.children = []

    @property
    def parent(self):
        return None if self._parent is None else self._parent()

    @parent.setter
    def parent(self, node):
        self._parent = weakref.ref(node, callback)

    def add_child(self, child):
        self.children.append(child)
        child.parent = self


def callback(ref):
    print '__del__', ref


n1 = Node(0)
n2 = Node(2)
print n1,n2
# <__main__.Node object at 0x7fb0c2750c10> <__main__.Node object at 0x7fb0c2750d10>
n1.add_child(n2)
del n1
# __del__ <weakref at 0x7fb0c26e75d0; dead>

不過(guò),如果我們使用 weakref.ref() 創(chuàng)建弱引用,每次使用時(shí)都需要形如這樣 xx() 來(lái)獲取,有一點(diǎn)別扭。 可以通過(guò) weakref.proxy() 這種來(lái)避免 () 操作。

n = Node(10)
p = weakref.proxy(n)
p.data
# 10
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容