適當地使用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