trap setting attribute when the attribute is dict
yosuke at ccwf.cc.utexas.edu
yosuke at ccwf.cc.utexas.edu
Mon Sep 3 15:47:55 EDT 2007
Arnaud Delobelle <arnodel at googlemail.com> wrote:
> On Sep 3, 7:00 pm, <yos... at ccwf.cc.utexas.edu> wrote:
>>
>> I want to do something like this. My class/instance has a dict as a
>> property. I want the instance to catch the change in the dict (change
>> in some values, addition/deletion of key/value etc) to be recognized by
>> the class instance.
>>
>> How can I do this? Any suggestions are very well appreciated.
>>
>> Here is an example of what I want my class to behave:
>>
>> class test(object):
>> def __init__(self):
>> self._d = {}
>> self._changed = False
>> def getd(self):
>> print 'called getd'
>> return self._d
>> # dont know what to do next
>> def setd(self,val):
>> print 'called setd', key, val
>> self._d[key] = val
> Where does the 'key' come from? Perhaps you need to look further into
> how properties work.
This obviously doesn't work...
>> self._changed = True
>> d = property(getd,setd,None,None)
>>
>> def getc(self):
>> return self._changed
>> changed = property(getc,None,None,None)
>>
>> if __name__ == '__main__':
>> obj = test()
>> print 'obj.changed = ', obj.changed
>> print
>>
>> # I want obj to know that its propety d being changed here
>> print "t.d['a'] = 1"
>> obj.d['a'] = 1
>> print
>>
>> # I want the "changed" property to be True
>> print 'obj.changed = ', obj.changed
>>
> You can't do that with plain dicts, and I'm not sure it is often a
> good idea. However you could create a class that behaves like a dict
> but calls a function each time an item is set, e.g. (made up
> terminology):
>>>> class TriggerDict(object):
> ... def __init__(self, trigger, val=None):
> ... self.trigger = trigger
> ... self.dict_ = val or {}
> ... def __setitem__(self, key, val):
> ... self.trigger(self, key, val)
> ... self.dict_[key] = val
> ... def __getitem__(self, key):
> ... return self.dict_[key]
> ...
>>>> def trigger(d, k, v):
> ... print '%s => %s' % (k, v)
> ...
>>>> td = TriggerDict(trigger)
>>>> td['spanish'] = 'inquisition' # see side effect below.
> spanish => inquisition
>>>> td['spanish']
> 'inquisition'
>>>>
> Obviously your trigger function would set the _changed attribute of
> the test object instead. And again it is probably not a good idea
> unless you know exactly what you are doing. If it was me, I'd try to
> rethink my design instead.
Thank you for suggestion, Arnaud.
Since you are discouraging this idea of trigger, may I ask an advice of
if my intention was legitimate one or not?
My intention was to have a propery 'sum' in my object, and which has sum
of all the values() of the dict (i have code to make sure that the value
of dict are all numeric). I could just the propery being calculated
everytime the property got __getattr__. But I thought that it was
inefficient to calculate the same number over and over when the value is
already known. So I was thiking of calculating the number only when the
dict got modified.
I also experimented with the idea of subclassing dict itself to
calculate the sum. Is this what would be better solution?
Thank you again,
> --
> Arnaud
--
yosuke kimura
Center for Energy and Environmental Resources
The Univ. of Texas at Austin, USA
More information about the Python-list
mailing list