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

Reply via email to