I have a code in which class instances have a parent β child link to each other, for example:
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()
I think this creates circular links, so that root , c1 and c2 will not be freed after Run () is complete, right ?. So how to free them? I think I can do something like root.children.clear() or self.parent = None - but what if I don't know when to do it?
Is this a good time to use weakref? What exactly, I poorly understand? parent attribute? children attribute The whole object? All of the above? I see talk about WeakKeyDictionary and weakref.proxy, but it's unclear how to use them, if at all possible.
This is also on python2.4 (cannot be updated).
Update: Example and Summary
Which objects for weakref-ify depend on which object can live without the other, and which objects depend on each other. The object that lives the longest should contain weak references to objects with a shorter period. Similarly, weaknesses should not be related to dependencies - if they are, the addiction can disappear silently, even if it is still needed.
If, for example, you have a tree structure, root , which has children, kids , but can exist without children, then the root object should use weakrefs for its kids . This also occurs if the child is dependent on the existence of the parent. Below, the child requires a parent to calculate its depth, and therefore strong-ref for parent . Elements of the kids attribute are optional, so weak links are used to prevent circular references.
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.
To flip the relationship around, we have something like below. Here, Facade classes require the Subsystem instance to work, so they use a strong reference to the subsystem they need. Subsystem s, however, does not require Facade . Subsystem simply specify how Facade notified of each other's actions.
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