@@ -111,7 +111,10 @@ def __getstate__(self):
111
111
def __setstate__ (self , data_dict ):
112
112
self .__dict__ = data_dict
113
113
# turn the normal dictionary back into a dictionary with weak values
114
- self ._parents = {k : weakref .ref (v )
114
+ # The extra lambda is to provide a callback to remove dead
115
+ # weakrefs from the dictionary when garbage collection is done.
116
+ self ._parents = {k : weakref .ref (v , lambda ref , sid = k , target = self :
117
+ target .pop (sid ))
115
118
for k , v in self ._parents .items () if v is not None }
116
119
117
120
def __copy__ (self , * args ):
@@ -169,7 +172,12 @@ def set_children(self, *children):
169
172
# parents are destroyed, references from the children won't
170
173
# keep them alive.
171
174
for child in children :
172
- 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
173
181
174
182
if DEBUG :
175
183
_set_children = set_children
0 commit comments