How can I use __setitem__ method of dict object?

jeremito jeremit0 at gmail.com
Tue Feb 6 11:42:55 EST 2007


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:
>
>
>
> > Please excuse me if this is obvious to others, but I can't figure it
> > out.  I am subclassing dict, but want to prevent direct changing of
> > some key/value pairs.  For this I thought I should override the
> > __setitem__ method as such:
>
> > class xs(dict):
> >     """
> >     XS is a container object to hold information about cross sections.
> >     """
>
> >     def __new__(cls, xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
> >         """
> >         """
> >         x = {}
> >         x['xS'] = xS
> >         x['xF'] = xF
> >         x['nu'] = nu
> >         x['xG'] = xG
> >         x['xA'] = x['xG'] + x['xF']
> >         x['xT'] = x['xA'] + x['xS']
>
> >         return x
>
> replace this with:
>     def __init__(self,  xS=1.0, xF=1.0, xG=1.0, nu=1.0, debug=0):
>            dict.__init__(
>                self,
>                xS=xS,
>                xF=xF,
>                xG=xG,
>               nu=nu,
>               xA=xG + xF,
>               xT=xG + xF + xS
>          )
>
> >     def __setitem__(self, key, value):
> >         """
> >         I have overridden this method to prevent setting xT or xA
> > outside the
> >         class.
> >         """
> >         print "I am in __setitem__"
> >         if key == 'xT':
> >             raise AttributeError(
>
>                   "Can't change xT.  Please change, xF, xS, or xG"
>                )
>            dict.__setitem__(self, key, value)
>
> > 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?  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?


>
> > Example:
> > Python 2.5 (r25:51918, Sep 19 2006, 08:49:13)
> > [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
> > Type "help", "copyright", "credits" or "license" for more information.>>> import xs
> > >>> cs = xs.xs()
> > >>> cs
>
> > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT': 3.0}>>> cs['xT'] = 3.1415
> > >>> cs
>
> > {'xA': 2.0, 'xF': 1.0, 'xG': 1.0, 'xS': 1.0, 'nu': 1.0, 'xT':
> > 3.1415000000000002}
>
> > 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.

> 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.

>
> My 2 cents...

Thanks again,
Jeremy




More information about the Python-list mailing list