I'm in need of a list of weak references that deletes items when they die. Currently the only way I have of doing this is to keep flushing the list (removing dead references manually).
I'm aware there's a WeakKeyDictionary and a WeakValueDictionary, but I'm really after a WeakList, is there a way of doing this?
Here's an example:
import weakref
class A(object):
def __init__(self):
pass
class B(object):
def __init__(self):
self._references = []
def addReference(self, obj):
self._references.append(weakref.ref(obj))
def flush(self):
toRemove = []
for ref in self._references:
if ref() is None:
toRemove.append(ref)
for item in toRemove:
self._references.remove(item)
b = B()
a1 = A()
b.addReference(a1)
a2 = A()
b.addReference(a2)
del a1
b.flush()
del a2
b.flush()
As I needed a weakref list like you, I've made one and publish it on pypi.
now you can do:
then:
You could implement it yourself, similarly to how you have done, but with a list subclass that calls flush() before attempting to access an item.
Obviously you don't want to do this on every access, but you can optimize this by setting a callback on the weak reference to mark the list dirty when something dies. Then you only need to flush the list when something has died since the last access.
Here's a list class implemented using this method. (Note that it's not tested much, and some methods aren't implemented very efficiently (eg. those which just convert to a real list and call the method on that), but it should be a reasonable starting point:
[Edit] Add a more complete list implementation.
Use a callback function passed to second argument of a weakref.
This code should function:
You can use WeakSet from the very same weakref module (it's actually defined elsewhere by the way, but it's imported there).
Why can't you just do it like this:
And then do similar for
__iadd__
,extend
etc. Works for me.How do you plan on using
B
? The only thing I ever do with the weakref list I built is iterate over it, so its implementation is simple: