python weakrefの理解
2272 ワード
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="">
親ノードのポインタは子供ノードを指し、子供ノードは親ノードを指します.これは循環参照を構成するため、オブジェクトごとの参照数が0になることはありません.
gcモジュールを手動で使用してゴミ回収を行うことができます
import gc
gc.collect()
残念なことに、ここで循環参照するオブジェクトは
__del__
メソッドを実現しています.gcモジュールは、どのオブジェクトの__del__
メソッドを先に呼び出すべきか分からないため、これらのオブジェクトを破棄しません.gcモジュールは、このようなオブジェクトをgcに配置する.garbageでは、オブジェクトは破棄されません.n1 = Node(1)
n2 = Node(2)
print n1, n2
# <__main__.node object="" at=""> <__main__.node object="" at="">
n1.add_child(n2)
del n1
del n2
gc.collect()
# 64
gc.garbage
# [<__main__.node object="" at=""> <__main__.node object="" at="">]
Weakrefで解決できます.オブジェクトに弱い参照が1つしか残っていない場合は、ゴミ回収できます.
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=""> <__main__.node object="" at="">
n1.add_child(n2)
del n1
# __del__
しかし、weakrefを使用すると.ref()は弱い参照を作成し、使用するたびにxx()のように取得する必要があり、少し違和感があります.weakref.proxy()は、()操作を避けるために使用されます.
n = Node(10)
p = weakref.proxy(n)
p.data
# 10