Observer-Pattern by (simple) decorator
Peter Otten
__peter__ at web.de
Sat Jun 2 10:00:48 EDT 2007
Wildemar Wildenburger wrote:
> David Wahler wrote:
>> Is this desired behavior?
>>
>>
>>>>> a = SomeActor()
>>>>> b = SomeActor()
>>>>> a.meth.observers is b.meth.observers
>>>>>
>> True
>>
> No it's not, but I get
>
>>>> a = SomeActor()
>>>> b = SomeActor()
>>>> a.meth.observers is b.meth.observers
> False
Then you have modified the code posted by Steven Bethard.
> I don't see how your behaviour should come about ... a new observer-list
> is created for every decorated method, so there is no problem.
Yes, but that list is shared across instances of SomeActor.
> Now I'm confused ?-|
You start with one Observable per method:
>>> SomeActor.meth
<tmp.Observable object at 0x401d5b0c>
>>> SomeActor.meth is SomeActor.meth
True
This Observable knows nothing about a SomeActor instance (because there is
none).
>>> SomeActor.meth.instance is None
True
Everytime you access meth from a SomeActor instance the __get__() method is
invoked and a new Observable is created, this time with an instance:
>>> SomeActor().meth is SomeActor.meth
False
>>> SomeActor().meth.instance
<tmp.SomeActor object at 0x401d56ec>
But all of these Observables share the same observables list
>>> SomeActor().meth.observers is SomeActor.meth.observers
True
>>> SomeActor().meth.observers is SomeActor().meth.observers
True
If you want per-instance callbacks you have to store the observers list (or
the bound method) in the instance:
>>> class SomeActor(object):
... def __init__(self):
... self.meth = Observable(self.meth, self)
... def meth(self, foo): print foo
...
>>> a = SomeActor()
>>> b = SomeActor()
>>> def make_callback(s):
... def f(instance):
... print s, instance
... return f
...
>>> a.meth.add_callback(make_callback("alpha"))
>>> b.meth.add_callback(make_callback("beta"))
>>> a.meth(1)
1
alpha <__main__.SomeActor object at 0x401d5c6c>
>>> b.meth(2)
2
beta <__main__.SomeActor object at 0x401d5ccc>
Note that with this approach Observable need not be a descriptor; I was just
too lazy to rewrite it.
Peter
More information about the Python-list
mailing list