I really dislike this approach to loop a list of weakrefs, see if they're still not garbage collected and if they're not perform some operation on the item and then later remove all those stale refs from an array
remove_me = []
for ui_control in self.list_of_weak_references_to_UI_controls:
ui_control = control_weak()
if ui_control: # if this weak ref is valid, enable or disable the UI control
ui_control.enabled = enable
else:
remove_me.append(ui_control)
for ui_control in remove_me:
self.list_of_weak_references_to_UI_controls.remove(ui_control)
Is there a pythonic way to do this compactly? I guess it's a rather common occurrence with weakrefs
Instead of creating and handling the weak references manually with weakref.ref
, and then checking if they are alive like you do, just use one of the higher level containers on the weakref module.
Not only dead references are removed automatically: any code needing the instances weak-referenced can just retrieve the instance from the container, and use it directy, with no workaround.
If you use a weakref.WeakSet
all your code above is simply not needed, but for the part that sets the enabled
attribute
# on the code creating the weakrefernces, instead of
# self.list_of_weak_references_to_UI_controls = []
# for item in original_source:
# self.list_of_weak_references_to_UI_controls.append(weakref.ref(item))
# do:
self.weak_references_to_UI_controls = weakref.WeakSet()
for item in original_source:
self.weak_references_to_UI_controls.add(item)
...
# And then, in the place you have your checking code you simply do:
for ui_control in self.weak_references_to_UI_controls:
ui_control.enabled = enable
# past the for loop, delete the "ui_control", as it is a strong reference
# that might leak:
del ui_control