sublcassing dict without losing functionality

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven Bethard

    #1

    sublcassing dict without losing functionality

    I'd like to subclass dict to disallow overwriting of keys, something like:
    [color=blue][color=green][color=darkred]
    >>> class SafeDict(dict):[/color][/color][/color]
    .... def __setitem__(sel f, key, value):
    .... if key in self:
    .... raise KeyError('canno t assign value %r to key %r, value %r'
    .... 'already exists' % (value, key, self[key]))
    .... super(SafeDict, self).__setitem __(key, value)
    ....

    The problem is, dict doesn't appear to call __setitem__ in any of the
    __init__ forms, so none of the following raise errors as I'd like them
    to:
    [color=blue][color=green][color=darkred]
    >>> SafeDict({'one' :1}, one=2)[/color][/color][/color]
    {'one': 2}[color=blue][color=green][color=darkred]
    >>> SafeDict([('one', 1), ('one', 2)])[/color][/color][/color]
    {'one': 2}[color=blue][color=green][color=darkred]
    >>> SafeDict([('one', 1), ('one', 2)], one=3)[/color][/color][/color]
    {'one': 3}[color=blue][color=green][color=darkred]
    >>> SafeDict(('one' , x) for x in (1, 2))[/color][/color][/color]
    {'one': 2}

    etc. Is there a simple way to override this behavior in dict without
    having to rewrite __init__? There are so many cases in dict.__init__
    that I'm hesitant to try to reproduce them all...

    Steve
    --
    You can wordify anything if you just verb it.
    - Bucky Katt, Get Fuzzy
  • Mathias Waack

    #2
    Re: sublcassing dict without losing functionality

    Steven Bethard wrote:
    [color=blue]
    > I'd like to subclass dict to disallow overwriting of keys,
    > something like:[/color]

    <snip>
    [color=blue]
    > The problem is, dict doesn't appear to call __setitem__ in any of
    > the __init__ forms, so none of the following raise errors as I'd
    > like them to:[/color]

    <snap>
    [color=blue]
    > etc. Is there a simple way to override this behavior in dict
    > without
    > having to rewrite __init__? There are so many cases in
    > dict.__init__ that I'm hesitant to try to reproduce them all...[/color]

    How about starting with UserDict (source comes with your python
    distribution) and modifying it for your needs?

    Mathias

    Comment

    • Steve Holden

      #3
      Re: sublcassing dict without losing functionality

      Mathias Waack wrote:
      [color=blue]
      > Steven Bethard wrote:
      >
      >[color=green]
      >>I'd like to subclass dict to disallow overwriting of keys,
      >>something like:[/color]
      >
      >
      > <snip>
      >[color=green]
      >>The problem is, dict doesn't appear to call __setitem__ in any of
      >>the __init__ forms, so none of the following raise errors as I'd
      >>like them to:[/color]
      >
      >
      > <snap>
      >[color=green]
      >>etc. Is there a simple way to override this behavior in dict
      >>without
      >>having to rewrite __init__? There are so many cases in
      >>dict.__init __ that I'm hesitant to try to reproduce them all...[/color]
      >
      >
      > How about starting with UserDict (source comes with your python
      > distribution) and modifying it for your needs?
      >[/color]

      Well, here's one reason I can think of:
      [color=blue][color=green][color=darkred]
      >>> from UserDict import UserDict
      >>> issubclass(User Dict, object)[/color][/color][/color]
      0[color=blue][color=green][color=darkred]
      >>> issubclass(dict , object)[/color][/color][/color]
      1[color=blue][color=green][color=darkred]
      >>> d = UserDict()
      >>> type(d)[/color][/color][/color]
      <type 'instance'>

      UserDict is an old-style class. Simply converting it to use object as a
      metaclass won't get you anywhere near the speed of a true dict.

      regards
      Steve
      --


      Holden Web LLC +1 800 494 3119

      Comment

      • Steven Bethard

        #4
        Re: sublcassing dict without losing functionality

        Mathias Waack <M.Waack <at> gmx.de> writes:[color=blue]
        >
        > How about starting with UserDict (source comes with your python
        > distribution) and modifying it for your needs?[/color]

        I'm trying to avoid a huge code bloat for something that should be relatively
        simple. Modifying and using UserDict would give me some 60+ lines of code to do
        something I would hope could be done in much less. A somewhat better option
        might be to copy/paste and slightly modify the __init__ and update code from
        UserDict which do more or less what I want... But of course, this has the
        problem of any copy/paste solution -- it will inevitably turn into a pain to
        sync. What happens if dict acquires a new keyword argument? I have to update
        my class again...

        The code is not hard to write, but it *is* already written for the dict object.
        If there's any way to take advantage of that fact, I'd like to.

        Steve

        Comment

        • Peter Otten

          #5
          Re: sublcassing dict without losing functionality

          Steven Bethard wrote:
          [color=blue]
          > simple. Modifying and using UserDict would give me some 60+ lines of code[/color]

          Not tested beyond what you see:
          [color=blue][color=green][color=darkred]
          >>> import UserDict as userdict
          >>> class Dict(userdict.D ictMixin, dict):[/color][/color][/color]
          .... def __setitem__(sel f, key, value):
          .... if key in self: raise ValueError("key already exists")
          .... super(Dict, self).__setitem __(key, value)
          .... def __init__(self, other=None, **kw):
          .... super(Dict, self).__init__( )
          .... self.update(oth er, **kw)
          ....[color=blue][color=green][color=darkred]
          >>> d = Dict({"one": 1}, one=2)[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          File "<stdin>", line 7, in __init__
          File "UserDict.p y", line 155, in update
          self.update(kwa rgs)
          File "UserDict.p y", line 147, in update
          self[k] = v
          File "<stdin>", line 3, in __setitem__
          ValueError: key already exists[color=blue][color=green][color=darkred]
          >>> d["one"] = 3[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          File "<stdin>", line 3, in __setitem__
          ValueError: key already exists[color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          Peter

          Comment

          Working...