WeakDict's are very similar to normal Python dictionaries, with the following essential exceptions:
WeakValue
(or a derived class)
WeakDict's have an asymptotic timing efficiency similar to normal Python dicts. Deletion of WeakValue's can take linear time in the number of uses in WeakDict's.
The implementation is mostly in the Python module weakdict
with some functions realized in _weakdict.c.
README file for details.
from weakdict import WeakValue, WeakDict
class TreeNode(WeakValue):
"""a tree node with list of children and parent reference."""
_children= _parent= None
def __init__(self): # would usually have more parameters
WeakValue.__init__(self)
def getChildren(self):
"""returns children tuple of *self*."""
children= self._children
if children is None: return ()
return tuple(children)
def getParent(self):
"""returns parent of *self*; 'None' if there is no parent."""
p= self._parent
if p is None: return None
else:
# p is a WeakDict
return p.get('parent')
def insertBefore(self,node,before=None):
"""inserts *node* as child before *before*; if *before* in 'None',
*node* becomes the last child."""
children= self._children
if children is None: children= self._children= []
if before is None: children.append(node)
else:
i= children.index(before)
children.insert(i,node)
node._setParent(self)
def _setParent(self,parent):
"""sets the parent reference to *parent*.
A WeakDict is used to represent the reference in order to avoid cycles.
"""
parentref= self._parent
if parentref is None: parentref= self._parent= WeakDict()
parentref['parent']= parent
def Main():
"""Build a tree, get reference to a leaf, then kill the tree."""
root= TreeNode()
innerNode= TreeNode(); root.insertBefore(innerNode,None)
leaf= TreeNode(); innerNode.insertBefore(leaf,None)
print "the tree is a chain of 3 elements: root, innernode, leaf"
print 'leaf.getParent(), innerNode:', leaf.getParent(), innerNode
print 'innerNode.getParent(), root:', innerNode.getParent(), root
print "del root: innernode looses its parent"
del root
print 'innerNode.getParent():', innerNode.getParent()
print "del innerNode: leaf looses its parent"
del innerNode
print 'leaf.getParent():', leaf.getParent()
if __name__ == '__main__':
Main()
has_key and __getitem__
on a new, still empty weakdict resulted in a SystemException.
__setitem__ with a non hashable key
caused (correctly) a type error but screwed up the weak value
such that a segment violation resulted, when the weak value
was finally deleted.