Group: comp.lang.python


Subject: detecting property modification
From: Jean-Paul Calderone
Date: 12/21/2007 1:11:55 PM
On Fri, 21 Dec 2007 09:49:51 -0800 (PST), Mangabasi <mangabasi@gmail.com> wrote: > [snip] > >Hi Jean-Paul, > >Sorry, I should have spelled this out in my post but I did not. For >several reasons I do not wish to couple the pos object with the Body >instances. In my case, I did not want pos objects (in my example they >were lists but they can be other objects as well) to care about their >parents. So the question is: How do we detect this in the Body? > You can't. If you have this: b = Body([1, 2]) b.pos[0] = 3 Then Body gets asked for the value of the attribute; then, that object (a list in the case of this example) gets told to change its 0th element to 3. There is no way for Body to get in the way of the second message, except by doing what I said - adding a wrapper around the list so that it _can_ get in the way. This doesn't require the list to know anything about Body, though. _Body_ should apply the wrapper. For example, new-style: class Body(object): def get_pos(self): return ChangeNoticingListWrapper(self._pos) def set_pos(self, value): self._pos = value pos = property(get_pos, set_pos) def __init__(self, pos): self.pos = pos class ChangeNoticingListWrapper(object): def __init__(self, wrapped): self.wrapped = wrapped def __setitem__(self, index, value): print 'Changing', index, 'to', value self.wrapped[index] = value b = Body([1, 2]) b.pos[0] = 3 Jean-Paul

Subject: detecting property modification
From: Jean-Paul Calderone
Date: 12/21/2007 1:43:38 PM
On Fri, 21 Dec 2007 10:30:31 -0800 (PST), Mangabasi <mangabasi@gmail.com> wrote: >On Dec 21, 1:11 pm, Jean-Paul Calderone <exar...@divmod.com> wrote: >> On Fri, 21 Dec 2007 09:49:51 -0800 (PST), Mangabasi <mangab...@gmail.com> wrote: >> > [snip] >> >> >Hi Jean-Paul, >> >> >Sorry, I should have spelled this out in my post but I did not. For >> >several reasons I do not wish to couple the pos object with the Body >> >instances. In my case, I did not want pos objects (in my example they >> >were lists but they can be other objects as well) to care about their >> >parents. So the question is: How do we detect this in the Body? >> >> You can't. If you have this: >> >> b = Body([1, 2]) >> b.pos[0] = 3 >> >> Then Body gets asked for the value of the attribute; then, that >> object (a list in the case of this example) gets told to change >> its 0th element to 3. There is no way for Body to get in the >> way of the second message, except by doing what I said - adding >> a wrapper around the list so that it _can_ get in the way. >> >> This doesn't require the list to know anything about Body, though. >> _Body_ should apply the wrapper. >> >> For example, new-style: >> >> class Body(object): >> def get_pos(self): >> return ChangeNoticingListWrapper(self._pos) >> def set_pos(self, value): >> self._pos = value >> pos = property(get_pos, set_pos) >> def __init__(self, pos): >> self.pos = pos >> >> class ChangeNoticingListWrapper(object): >> def __init__(self, wrapped): >> self.wrapped = wrapped >> def __setitem__(self, index, value): >> print 'Changing', index, 'to', value >> self.wrapped[index] = value >> >> b = Body([1, 2]) >> b.pos[0] = 3 >> >> Jean-Paul > > >Hi Jean-Paul, > >I see what you are saying but my contrived example is not doing a good >job explaining the real issue I am having here. > >When you say "The Body gets asked for the value of the attribute" that >means that Body's __dict__ is being asked to provide a value >corresponding to its 'pos' key, right? Now I may want to ask a more >specific question here. How do I modify Body's __dict__ so that I can >perform a task when __getitem__ method of the __dict__ is called? You can't do that. Fortunately, there's no reason to. Changing the behavior of __getitem__ on the __dict__ of a Body instance would let you address the exact same use-case as a property or a __getattr__ implementation lets you address. Maybe you are asking whether there is a special method called __getitem__ which is invoked when attributes are looked up? If so, yes, there is. You can also use a property, as in the example I gave. None of that has anything to do with looking up values in the result of the attribute lookup, though. For example, it doesn't help you change the behavior of "pos[0]". Jean-Paul