On Sun, Feb 22, 2015 at 7:22 AM, Cem Karan <cfkar...@gmail.com> wrote: > > On Feb 22, 2015, at 5:15 AM, Gregory Ewing <greg.ew...@canterbury.ac.nz> > wrote: > >> Frank Millman wrote: >>> "In order to inform users that certain bits of state have changed, I >>> require them to register a callback with my code." >>> This sounds to me like a pub/sub scenario. When a 'listener' object comes >>> into existence it is passed a reference to a 'controller' object that holds >>> state. It wants to be informed when the state changes, so it registers a >>> callback function with the controller. >> >> Perhaps instead of registering a callback function, you >> should be registering the listener object together with >> a method name. >> >> You can then keep a weak reference to the listener object, >> since if it is no longer referenced elsewhere, it presumably >> no longer needs to be notified of anything. > > I see what you're saying, but I don't think it gains us too much. If I store > an object and an unbound method of the object, or if I store the bound method > directly, I suspect it will yield approximately the same results.
Well, it ties the weak ref to the lifetime of the object owning the callback rather than to the lifetime of the potentially unreferenced callback itself. I'm not fond of the scheme though because it forces the callback to be a method, and I'd prefer not to make that assumption. Also, I just noticed that Python 3.4 adds a weakref.WeakMethod class that solves the problem for the bound method case. That still leaves the closure and lambda cases, but here's a thought: add an optional argument to the callback registration method that specifies what object to tie the weak ref to. Something like: class Listenable: def __init__(self): self._callbacks = weakref.WeakKeyDictionary() def listen(self, callback, owner=None): if owner is None: if isinstance(callback, types.MethodType): owner = weakref.WeakMethod(callback) else: owner = callback self._callbacks.setdefault(owner, []).append(callback) def do_callbacks(self, message): for callbacks in self._callbacks.values(): for callback in callbacks: callback(message) -- https://mail.python.org/mailman/listinfo/python-list