适当地使用weakref我有一些代码,其中的类的实例有家长< - >子引用对方,如:如何以及何时在Python
class Node(object):
def __init__(self):
self.parent = None
self.children = {}
def AddChild(self, name, child):
child.parent = self
self.children[name] = child
def Run():
root, c1, c2 = Node(), Node(), Node()
root.AddChild("first", c1)
root.AddChild("second", c2)
Run()
我认为这将创建循环引用,使得在Run()完成后,root
,c1
和c2
不会被释放,对吗?那么,如何让他们获得释放?我想我可以做点像root.children.clear()
或self.parent = None
- 但是如果我不知道什么时候该做什么?
这是一个适当的时间来使用weakref模块?什么,确切地说,我弱化refrefify? parent
属性? children
属性?整个对象?上述所有的?我看到关于WeakKeyDictionary和weakref.proxy的讨论,但我不清楚在这种情况下应该如何使用它们。
这也是python2.4(不能升级)。
更新:互相依赖的例子和总结
什么反对weakref-IFY取决于哪个对象生活中可以没有其他的,什么对象。寿命最长的物体应该包含较短寿命物体的弱点。类似地,不应该对依赖关系进行弱引发 - 如果是这样,依赖关系可能会默默地消失,即使它仍然是需要的。
如果,例如,你有一个树状结构,root
,有孩子,kids
,但可以存在没有孩子,那么root
对象应使用weakrefs其kids
。如果子对象取决于父对象的存在,情况也是如此。在下面,子对象要求父母为来计算其深度,因此为parent
的强引用。尽管kids
属性的成员是可选的,但是使用weakrefs来防止循环引用。
class Node:
def __init__(self)
self.parent = None
self.kids = weakref.WeakValueDictionary()
def GetDepth(self):
root, depth = self, 0
while root:
depth += 1
root = root.parent
return depth
root = Node()
root.kids["one"] = Node()
root.kids["two"] = Node()
# do what you will with root or sub-trees of it.
要翻转关系,我们有如下所示。在这里,Facade
类需要一个Subsystem
实例才能工作,所以他们使用强引用到他们需要的子系统。然而,Subsystem
不需要Facade
工作。 Subsystem
只是提供一种方式来通知Facade
关于彼此的行为。
class Facade:
def __init__(self, subsystem)
self.subsystem = subsystem
subsystem.Register(self)
class Subsystem:
def __init__(self):
self.notify = []
def Register(self, who):
self.notify.append(weakref.proxy(who))
sub = Subsystem()
f1 = CliFacade(sub)
f2 = WebFacade(sub)
# Go on to reading from POST, stdin, etc
另外,如果您确定不需要循环gc,则可以禁用它以实现小的性能提升。 – 2009-10-02 05:11:50
谢谢,亚历克斯。是否有一个特定的原因来弱报告“children”而不是'parent'?效果会一样吗?如果'父母'也是弱refref会发生什么?在双链表的情况下,“prev”,“next”还是两者都应该是weakrefs? – 2009-10-02 08:08:08
这是不好的建议。示例中的所有子节点将在从Run()返回后立即被破坏。一般来说,你几乎总是把一个结构体的根绑定到变量上,所以正确的方法是将'weakref'用于'parent',而不是'children'。 – 2009-10-02 08:10:04