By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,620 Members | 1,512 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,620 IT Pros & Developers. It's quick & easy.

sublcassing dict without losing functionality

P: n/a
I'd like to subclass dict to disallow overwriting of keys, something like:
class SafeDict(dict): .... 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
--
You can wordify anything if you just verb it.
- Bucky Katt, Get Fuzzy
Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Steven Bethard wrote:
I'd like to subclass dict to disallow overwriting of keys,
something like:
<snip>
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:
<snap>
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
Jul 18 '05 #2

P: n/a
Mathias Waack wrote:
Steven Bethard wrote:

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

<snip>
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:

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


Well, here's one reason I can think of:
from UserDict import UserDict
issubclass(UserDict, object) 0 issubclass(dict, object) 1 d = UserDict()
type(d)

<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
--
http://www.holdenweb.com
http://pydish.holdenweb.com
Holden Web LLC +1 800 494 3119
Jul 18 '05 #3

P: n/a
Mathias Waack <M.Waack <at> gmx.de> writes:

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

Jul 18 '05 #4

P: n/a
Steven Bethard wrote:
simple. Modifying and using UserDict would give me some 60+ lines of code


Not tested beyond what you see:
import UserDict as userdict
class Dict(userdict.DictMixin, dict): .... 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)
.... d = Dict({"one": 1}, one=2) 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 "<stdin>", line 3, in __setitem__
ValueError: key already exists d["one"] = 3 Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __setitem__
ValueError: key already exists


Peter

Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.