@@ -110,7 +110,11 @@ def __getstate__(self):
110110 def __setstate__ (self , data_dict ):
111111 self .__dict__ = data_dict
112112 # turn the normal dictionary back into a dictionary with weak values
113- self ._parents = {k : weakref .ref (v )
113+ # The extra lambda is to provide a callback to remove dead
114+ # weakrefs from the dictionary when garbage collection is done.
115+ self ._parents = {k : weakref .ref (v , lambda ref , sid = k ,
116+ target = self ._parents :
117+ target .pop (sid ))
114118 for k , v in self ._parents .items () if v is not None }
115119
116120 def __copy__ (self , * args ):
@@ -168,7 +172,12 @@ def set_children(self, *children):
168172 # parents are destroyed, references from the children won't
169173 # keep them alive.
170174 for child in children :
171- child ._parents [id (self )] = weakref .ref (self )
175+ # Use weak references so this dictionary won't keep obsolete nodes
176+ # alive; the callback deletes the dictionary entry. This is a
177+ # performance improvement over using WeakValueDictionary.
178+ ref = weakref .ref (self , lambda ref , sid = id (self ),
179+ target = child ._parents : target .pop (sid ))
180+ child ._parents [id (self )] = ref
172181
173182 if DEBUG :
174183 _set_children = set_children
0 commit comments