I would like to use the functionality of a weakref.WeakSet, but in this set I would like to store bound methods, so I have to use weakref.WeakMethod.
Here's a stripped down example:
import weakref
class C:
def method(self): pass
ci = C()
print("weakMethod:", weakref.WeakMethod(ci.method))
print("s1:", weakref.WeakSet([C.method]))
print("s2:", weakref.WeakSet([ci.method]))
print("s3:", weakref.WeakSet([weakref.WeakMethod(ci.method)]))
which gives me (with Python 3.12.2)
weakMethod: <weakref at 0x7f569e9308d0; to 'C' at 0x7f569e96dca0>
s1: {<weakref at 0x7f56ac12a520; to 'function' at 0x7f569e98ade0 (method)>}
s2: set()
s3: set()
As you can see in the first line, WeakMethod works as expected, but storing it in a WeakSet yields an empty s3.
Side note: s2 is empty as expected, but storing a weak reference to an unbound method as in s1 works.
Obvious workaround: Use a set instead of a WeakSet and replicate its functionality.
Question: Is there a more elegant way of combining the functionality of WeakSet and WeakMethod?
Here's the current "obvious" workaround I use in the context of an observer pattern:
which outputs:
Notice that the
setdoes a great job and boils the five equal observers down to a single observer and theWeakMethodremoves to observer afterdel acme. If you replace theWeakMethodwith a direct reference, it will keepacmeand its observer alive despite thedel acme(which is exactly what I try to avoid).Ok, this works, but I'm curious if you have a more elegant solution using
WeakSet.