override a property

Steven Bethard steven.bethard at gmail.com
Tue Oct 18 14:27:14 EDT 2005


Robin Becker wrote:
> ## my silly example
> class ObserverProperty(property):
>     def __init__(self,name,observers=None,validator=None):
>         self._name = name
>         self._observers = observers or []
>         self._validator = validator or (lambda x: x)
>         self._pName = '_' + name
>         property.__init__(self,
>                 fset=lambda inst, value: self.__notify_fset(inst,value),
>                 )
> 
>     def __notify_fset(self,inst,value):
>         value = self._validator(value)
>         for obs in self._observers:
>             obs(inst,self._pName,value)
>         inst.__dict__[self._pName] = value
> 
>     def add(self,obs):
>         self._observers.append(obs)
> 
> def obs0(inst,pName,value):
>     print 'obs0', inst, pName, value
> 
> def obs1(inst,pName,value):
>     print 'obs1', inst, pName, value
> 
> class A(object):
>     x = ObserverProperty('x')
> 
> a=A()
> A.x.add(obs0)
> 
> a.x = 3
> 
> b = A()
> b.x = 4
> 
> #I wish I could get b to use obs1 instead of obs0
> #without doing the following
> class B(A):
>     x = ObserverProperty('x',observers=[obs1])
> 
> b.__class__ = B
> 
> b.x = 7

Can you add the object to be observed as another parameter to the add 
method?

py> class ObservableProperty(property):
...     def __init__(self, *args, **kwargs):
...         super(ObservableProperty, self).__init__(*args, **kwargs)
...         self._observers = {}
...     def __set__(self, obj, value):
...         super(ObservableProperty, self).__set__(obj, value)
...         for observer in self._observers.get(obj, []):
...             observer(obj)
...     def add(self, obj, observer):
...         self._observers.setdefault(obj, []).append(observer)
...
py> class A(object):
...     def _getx(self):
...         return self._x
...     def _setx(self, value):
...         self._x = value
...     x = ObservableProperty(_getx, _setx)
...
py> def obs1(obj):
...     print 'obs1:', obj.x
...
py> def obs2(obj):
...     print 'obs2:', obj.x
...
py> a = A()
py> a.x = 3
py> A.x.add(a, obs1)
py> a.x = 4
obs1: 4
py> A.x.add(a, obs2)
py> a.x = 5
obs1: 5
obs2: 5
py> b = A()
py> b.x = 6
py> A.x.add(b, obs2)
py> b.x = 7
obs2: 7

Probably "self._observers" should use some sort of weakref dict instead 
of a regular dict, but hopefully the idea is clear.

STeVe



More information about the Python-list mailing list