Observer-Pattern by (simple) decorator
Steven Bethard
steven.bethard at gmail.com
Fri Jun 1 19:27:10 EDT 2007
Wildemar Wildenburger wrote:
> I thought: I'll just write a decorator that lets me react to method
> calls easily (the ever so popular observer-pattern). I've looked at some
> recepies, but I just don't get them (I'm feeling kinda dumb today, sorry).
[snip]
> This is more complicated than expected mainly for two reasons:
>
> * I can't find a way to pass the proper 'instance' argument to
> callback, that is, I don't know how to retrieve the instance that
> meth() was called on, because the observable decorator only gets
> the *function* object but not the *method*. (I hope this was clear
> enough)
> * Also, I don't see how I could add the add_callback() method to the
> meth object. That doesn't seem possible. I can add it to meth's
> function object just fine in the definition of observable, but I
> thats not what I really want. This is probably just a cosmetic
> issue because I don't like the idea of calling
> sa.meth.im_func.add_callback(callback).
I think you want to define __get__ on your Observable class so that it
can do the right thing when the method is bound to the instance:
>>> class Observable(object):
... def __init__(self, func, instance=None, observers=None):
... if observers is None:
... observers = []
... self.func = func
... self.instance = instance
... self.observers = observers
... def __get__(self, obj, cls=None):
... if obj is None:
... return self
... else:
... func = self.func.__get__(obj, cls)
... return Observable(func, obj, self.observers)
... def __call__(self, *args, **kwargs):
... result = self.func(*args, **kwargs)
... for observer in self.observers:
... observer(self.instance)
... return result
... def add_callback(self, callback):
... self.observers.append(callback)
...
>>> class SomeActor(object):
... @Observable
... def meth(self, foo):
... print foo
...
>>> def callback(instance):
... print "Yippie, I've been called on", instance
... instance.bar = True
...
>>> sa = SomeActor()
>>> sa.meth.add_callback(callback)
>>> sa.meth("I'm the boring old argument")
I'm the boring old argument
Yippie, I've been called on <__main__.SomeActor object at 0x00E7A4D0>
>>> sa.bar
True
STeVe
More information about the Python-list
mailing list