<[EMAIL PROTECTED]> schrieb im Newsbeitrag news:[EMAIL PROTECTED] > Hello, > > I need a way to get a notification whenever a variable of an object > changes. The approach should be non-intrusive so that I can use > existing objects without modifying them. > I want to be notified no matter who or what did change the wrapped > object - even whenever an object internal methods changes the > variables. > So I coded the piece of code shown below (just copy and paste it, it's > ready-to-run). > It's basically a Proxy class that takes an object and whenever somebody > tries to access the proxy, the proxy forwards this to the real object. > Whenever a method of the obj gets called the proxy detects this and the > operation is performed on the the proxy object so that variable change > notifications can be send. > Since I am quite new to Python and the code does not 100% what I want, > I have the feeling, it's not optimal and that there might be a better > way to achieve what I want. For example I am not sure if really all > changes will be catched this way and if the method call re-routed to > proxy object is not a bit hackish. Second, type(Proxy()) doesn't return > the same as type(WrappedObj()). The proxy should behave identical to > the wrapped object. Should I do this with metaclasses to get the type > right or are there better ways? I am not sure if they could fit here or > not. > So, what do you think of this code and how should I improve it? > > Thanks a lot for your help! > > -Matthias
This may be help: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/366254 -- Vincent Wehren > > > Code (just copy and pasts and it should run): > > import inspect, new, sys > > class Proxy(object): > def __init__(self, wrappedObj): > # need to call object here to save objs to our own dict > object.__setattr__(self,'_wrappedObj',wrappedObj) > object.__setattr__(self,'_observers',{}) > > def __getattribute__(self, name): > # if attribute of proxy obj itself was queried return that > value > if name in ['_wrappedObj','_observers','Subscribe','Notify']: > return object.__getattribute__(self, name) > # otherwise get var from the wrapped object > attr = getattr( object.__getattribute__(self, '_wrappedObj'), > name ) > # make method use this proxy object instead of wrapped one to > catch updates > if inspect.ismethod( attr ): > return new.instancemethod( attr.im_func, self, > attr.im_class ) > else: > return attr > > def __setattr__(self, name, value): > # sets attribute of the wrapped value > setattr(object.__getattribute__(self,'_wrappedObj'), name, > value) > # notify me of change > object.__getattribute__(self,'Notify')('Changed',name, value) > > # Adds an observer > def Subscribe(self, function, event = ''): > self._observers.setdefault(event,[]).append(function) > > # Notifies all observers > def Notify(self, event = '', *args): > for observer in self._observers.get(event, []): > observer(*args) > > > class TestObj(object): > classVar = 'cv' > def __init__(self): > self.spam = '1' > > def method(self): > self.spam = '2' > > # create a proxy > p = Proxy(TestObj()) > > # print some info of it > print 'Proxy: %s ' % p > print 'Class of proxy: %s' % p.__class__ > print 'Type of proxy: %s <--- this sucks' % type(p) > print 'Dir of proxy: %s' % dir(p) > > # enable watching changes > p.Subscribe(lambda name, var: sys.stdout.write('%s was changed and is > now %s\n' % (name,var) ) ,'Changed') > > # change some stuff > p.method() > p.cv = 'new cv' > p.spam = 1 > p.func = lambda x: x-1 > print p.func(2) > -- http://mail.python.org/mailman/listinfo/python-list