Anders Dahnielson wrote: > Sorry if this is a somewhat silly question... > > I'm using the Observer implementation found in 'Patterns in > Python' [1] and find it really neat. But, I have not yet fully groked > the new-style class, classic class and property differences involved. > So can somebody please explain to me why this works (using a classic > class): > > class C: > TheEvent = Event() > def OnTheEvent(self): > self.TheEvent(self, context) > > instance = C() > instance.TheEvent += callback > instance.OnTheEvent() > instance.TheEvent -= callback > > While this do not (using new-style class): > > class C(object): > TheEvent = Event() > def OnTheEvent(self): > self.TheEvent(self, context) > > instance = C() > instance.TheEvent += callback > instance.OnTheEvent() > instance.TheEvent -= callback > > Raising an AttributeError : > > Traceback (most recent call last): > File "sig_test.py", line 7, in ? > instance.TheEvent += callback > AttributeError: can't set attribute > > So far I've figured out that it is the Event class (subclassing the > built-in property type) that is the culprit, but not why. (See > 'Patterns in Python' [1] for code listing of the Event class.) > > I would be grateful if some helpful soul could explain it. > > [1] http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html#observer >
This is because the object derived class C is behaving properly with respect to its property attributes. __iadd__() is supposed to set the attribute, but no setter is called because the property (an Event()) does not have a setter defined. The most straightforward fix would not be to define a setter in construction of Event instances, but would rather to come up with some other way than __iadd__ to specify changing the state of the delegates: # was __iadd__() def append(self, callback): self.__delegates = [ cb for cb in self.__delegates if getattr(cb, 'im_self', None) != callback] # If callback is callable, remove the last # matching callback if callable(callback): for i in range(len(self.__delegates)-1, -1, -1): if self.__delegates[i] == callback: del self.__delegates[i] break [...] d.append(function) The use of __iadd__ & __isub__ as described in the article allows a neat shorthand, but does not function correctly in the context of new style classes. James -- James Stroud UCLA-DOE Institute for Genomics and Proteomics Box 951570 Los Angeles, CA 90095 http://www.jamesstroud.com -- http://mail.python.org/mailman/listinfo/python-list