我有一些代码,其中类的实例具有彼此的父<->子引用,例如:
class Node:
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()
我认为这会创建循环引用root
,c1
并且c2
在 Run() 完成后不会被释放,对吧?那么,如何让他们获得自由呢?我想我可以做类似的事情root.children.clear()
,或者self.parent = None
- 但是如果我不知道什么时候做呢?
现在是使用weakref 模块的合适时机吗?我究竟要弱化什么?属性parent
?children
属性?整个对象?上述所有的?我看到有关 WeakKeyDictionary 和weakref.proxy 的讨论,但我不清楚在这种情况下应该如何使用它们(如果有的话)。
这也在 Python 2.4 上(无法升级)。
更新:示例和摘要
对哪些对象进行弱引用取决于哪些对象可以在没有另一个的情况下生存,以及哪些对象相互依赖。寿命最长的对象应该包含对寿命较短的对象的弱引用。类似地,不应该对依赖项进行弱引用 - 如果是,则即使仍然需要依赖项,也可能会默默地消失。
例如,如果您有一个树结构 ,root
有孩子 ,kids
但可以没有孩子而存在,那么该root
对象应该为其 . 使用弱引用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()
为了翻转关系,我们有类似下面的东西。在这里,这些Facade
类需要一个Subsystem
实例才能工作,因此它们对所需的子系统使用强引用。 Subsystem
但是,s 不需要 aFacade
来工作。 Subsystem
s 只是提供了一种方法来通知Facade
s 彼此的操作。
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()
cli = Facade(sub)