[Python-3000] weakrefs and cyclic references

Nick Coghlan ncoghlan at gmail.com
Fri Jun 2 12:53:39 CEST 2006

Greg Ewing wrote:
> What might be useful is an easier way of *explicitly*
> creating and using weak references.
> We already have WeakKeyDictionary and WeakValueDictionary
> which behave just like ordinary dicts except that they
> weakly reference things. I'm thinking it would be nice
> to have a way of declaring any attribute to be a weak
> reference. Then it could be read and written it in the
> usual way, without all the code that uses it having
> to know about its weakness.
> This could probably be done fairly easily with a suitable
> property descriptor.

Something like the following? (although you could do a simpler version without 
the callback support) (untested!)

class WeakAttr(object):
     """Descriptor to define weak instance attributes

     name is the name of the attribute
     callback is an optional callback function

     If supplied, the callback function is called with the
     instance and the attribute name as arguments after a currently
     referenced object is finalized.
     def __init__(self, name, callback=None):
         self._name = name
         self._callback = callback

     def __get__(self, obj, cls):
         if obj is None:
             return self
         attr_ref = getattr(obj, self._name)
         if attr_ref is not None:
             return attr_ref()
         return None

     def __set__(self, obj, value):
         name = self._name
         if value is None:
             setattr(obj, name, None)
             cb = self._callback
             if cb is not None:
                 _cb = cb
                 def cb(dead_ref):
                     if dead_ref is getattr(obj, name):
                         # Object that went away is still
                         # the one referred to by the
                         # attribute, so invoke the callback
                         _cb(obj, name)
             attr_ref = weakref.ref(value, cb)
             setattr(obj, self._name, )

     def __delete__(self, obj):
         delattr(obj, self._name)

Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-3000 mailing list