How can I use __setitem__ method of dict object?
jeremito
jeremit0 at gmail.com
Tue Feb 6 16:00:08 EST 2007
On Feb 6, 2:36 pm, Bruno Desthuilliers
<bdesth.quelquech... at free.quelquepart.fr> wrote:
> jeremito a écrit :
>
>
>
> > On Feb 6, 10:59 am, "bruno.desthuilli... at gmail.com"
> > <bruno.desthuilli... at gmail.com> wrote:
>
> >>On 6 fév, 16:23, "jeremito" <jerem... at gmail.com> wrote:
>
> (snip)
> >>>But I can't even get __setitem__ to run.
>
> >>of course, since your __new__ method returns a dict instance, not a xs
> >>instance...
> >>There are very few cases where you really need to override the __new__
> >>method.
>
> > The reason I create my object with __new__ instead of __init__ is
> > because when I use __init__ when a value is set it calls __setitem__.
> > This is what I want to happen, but not inside of __init__. Does this
> > make sense?
>
> It would make sens - if you couldn't call dict.__setitem__ directly.
>
>
>
>
>
> > I'm sure there is a better/more pythonic way to do this,
> > but I'm unsure of what it is. Can someone show me an example of how
> > this should work?
>
> (snip)
> >>>Is this what the __setitem__ method is for?
>
> >>Yes. But note that you you need to manually call the superclass's
> >>overriden method - unless you
> >>really want to replace it with your own, which is obviously not the
> >>case here...
>
> >>Note that if someone manually changes the values of xG, xF, or xS, the
> >>computed values of xA and/or xT
> >>won't reflect this change. Is that what you want ?
>
> > Eventually (when I figure out how to use __setitem__) I will change
> > what happens when xG, xF, or xS are changed so that it also changes xA
> > and xT.
>
> Which is not the best way to go IMHO. Unless the computation is very
> intensive (which doesn't seem to be the case here) or it's heavily used
> in big loops *and* the perfs are not good enough, it's better to
> recompute on the fly at read time. And if one of the above cases arises,
> then it will be time to use memoization (ie: cache the result of
> computation, invalidating the cache when needed).
>
>
>
> >>Finally, and if I may ask, what is your use-case for subclassing
> >>dict ? You don't need this to implement a dict-like object,
> >>and it might be simpler in your case to write an ordinary class, then
> >>add support for the required subset of the dict interface.
>
> > Eventually I am going to add other features to my class (as I have
> > mentioned) so I can't simply use a dict object.
>
> I already understood this. My question is : why do you want to
> *subclass* dict. In Python, inheritence is only about implementation,
> it's *not* needed for polymorphism to work. So you don't have to
> subclass dict to have an object behaving (more or less, that's up to
> you) like a dict.
>
> Here's an alternative implementation, so you get the idea. Note that it
> behaves mostly like a dict (well, not totally, but since we don't know
> which subset of the dict interface you need...), but also like a
> 'standard' object, so you can use either cs.['xT'] or cs.xT with the
> same result.
>
> class Xs(dict):
> """
> Xs is a container object to hold information about cross sections.
> """
> _computedkeys = 'xA', 'xT'
>
> def __init__(self, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
> self.xS = xS
> self.xF = xF
> self.xG = xG
> self.nu = nu
>
> # xA and xT as properties (AKA computed attributes)
> def _get_xA(self):
> return self.xG + self.xF
> def _set_xA(self, dummy):
> raise AttributeError(
> "%s.xA is read-only" % self.__class__.__name__
> )
> xA = property(fset=_set_xA, fget=_get_xA)
>
> def _get_xT(self):
> return self.xA + self.xS
> def _set_xT(self, dummy):
> raise AttributeError(
> "%s.xT is read-only" % self.__class__.__name__
> )
> xT = property(fset=_set_xT, fget=_get_xT)
>
> # dict interface support, to be extended if needed
> def __setitem__(self, key, value):
> setattr(self, key, value)
>
> def __getitem__(self, key):
> return getattr(self, key)
>
> def keys(self):
> return self.__dict__.keys() + list(self._computedkeys)
>
> def values(self):
> return self.__dict__.values() \
> + [getattr(self, key) for key in self._computedkeys]
>
> def items(self):
> return zip(self.keys(), self.values())
>
> def __iter__(self):
> for k in self.keys():
> yield k
> raise StopIteration
>
> def __contains__(self, key):
> return key in self.keys()
>
> def __repr__(self):
> return repr(dict(self.items()))
Thanks a lot for your help. I think what you have written is much
better than what I could have come up with on my own. I guess I just
need more experience.
Thanks,
Jeremy
More information about the Python-list
mailing list