sublcassing dict without losing functionality

S

Steven Bethard

I'd like to subclass dict to disallow overwriting of keys, something like:
.... def __setitem__(self, key, value):
.... if key in self:
.... raise KeyError('cannot 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:
SafeDict({'one':1}, one=2) {'one': 2}
SafeDict([('one', 1), ('one', 2)]) {'one': 2}
SafeDict([('one', 1), ('one', 2)], one=3) {'one': 3}
SafeDict(('one', x) for x in (1, 2))
{'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
 
M

Mathias Waack

Steven said:
I'd like to subclass dict to disallow overwriting of keys,
something like:

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:

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

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

Mathias
 
S

Steve Holden

Mathias said:
Steven Bethard wrote:










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

Well, here's one reason I can think of:
<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
 
S

Steven Bethard

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

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
 
P

Peter Otten

Steven said:
simple. Modifying and using UserDict would give me some 60+ lines of code

Not tested beyond what you see:
.... def __setitem__(self, 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(other, **kw)
....Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 7, in __init__
File "UserDict.py", line 155, in update
self.update(kwargs)
File "UserDict.py", line 147, in update
self[k] = v
File said:
Traceback (most recent call last):
File "<stdin>", line 1, in ?

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top