How can I use __setitem__ method of dict object?

bruno.desthuilliers at gmail.com bruno.desthuilliers at gmail.com
Tue Feb 6 10:59:39 EST 2007


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.

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

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.

My 2 cents...




More information about the Python-list mailing list