detecting property modification

Jean-Paul Calderone exarkun at divmod.com
Fri Dec 21 13:43:38 EST 2007


On Fri, 21 Dec 2007 10:30:31 -0800 (PST), Mangabasi <mangabasi at gmail.com> wrote:
>On Dec 21, 1:11 pm, Jean-Paul Calderone <exar... at divmod.com> wrote:
>> On Fri, 21 Dec 2007 09:49:51 -0800 (PST), Mangabasi <mangab... at 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



More information about the Python-list mailing list