diff options
author | Raymond Hettinger <python@rcn.com> | 2002-11-18 04:34:10 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2002-11-18 04:34:10 (GMT) |
commit | 8ddc176e2e7ef11b2c46062b29563bc776f177b8 (patch) | |
tree | 9420f4a710a3ae47f72c846c0b6f5e0c1a9a29bd /Lib/UserDict.py | |
parent | 782d9408667f8df924d865088839633f53cf89bc (diff) | |
download | cpython-8ddc176e2e7ef11b2c46062b29563bc776f177b8.zip cpython-8ddc176e2e7ef11b2c46062b29563bc776f177b8.tar.gz cpython-8ddc176e2e7ef11b2c46062b29563bc776f177b8.tar.bz2 |
Improve DictMixin.
Replaced docstring with comments. Prevents subclass contamination.
Added the missing __cmp__() method and a test for __cmp__().
Used try/except style in preference to has_key() followed by a look-up.
Used iteritem() where possible to save creating a long key list and
to save redundant lookups.
Expanded .update() to look for the most helpful methods first and gradually
work down to a mininum expected interface.
Expanded documentation to be more clear on how to use the class.
Diffstat (limited to 'Lib/UserDict.py')
-rw-r--r-- | Lib/UserDict.py | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/Lib/UserDict.py b/Lib/UserDict.py index b6b36b2..96f049d 100644 --- a/Lib/UserDict.py +++ b/Lib/UserDict.py @@ -62,13 +62,17 @@ class IterableUserDict(UserDict): return iter(self.data) class DictMixin: - '''Mixin defining all dictionary methods for classes that already have - a minimum dictionary interface including getitem, setitem, delitem, - and keys ''' + # Mixin defining all dictionary methods for classes that already have + # a minimum dictionary interface including getitem, setitem, delitem, + # and keys. Without knowledge of the subclass constructor, the mixin + # does not define __init__() or copy(). In addition to the four base + # methods, progessively more efficiency comes with defining + # __contains__(), __iter__(), and iteritems(). - # first level provided by subclass: getitem, setitem, delitem, and keys - - # second level definitions which assume only getitem and keys + # second level definitions support higher levels + def __iter__(self): + for k in self.keys(): + yield k def has_key(self, key): try: value = self[key] @@ -76,34 +80,30 @@ class DictMixin: return False return True __contains__ = has_key - def __iter__(self): - for k in self.keys(): - yield k - def __len__(self): - return len(self.keys()) - # third level uses second level instead of first + # third level takes advantage of second level definitions def iteritems(self): for k in self: yield (k, self[k]) iterkeys = __iter__ - # fourth level uses second and third levels instead of first + # fourth level uses definitions from lower levels def itervalues(self): for _, v in self.iteritems(): yield v def values(self): - return [self[key] for key in self.keys()] + return [v for _, v in self.iteritems()] def items(self): return list(self.iteritems()) def clear(self): for key in self.keys(): del self[key] def setdefault(self, key, default): - if key not in self: + try: + return self[key] + except KeyError: self[key] = default - return default - return self[key] + return default def pop(self, key): value = self[key] del self[key] @@ -112,15 +112,30 @@ class DictMixin: try: k, v = self.iteritems().next() except StopIteration: - raise KeyError, 'dictionary is empty' + raise KeyError, 'container is empty' del self[k] return (k, v) def update(self, other): - for key in other.keys(): - self[key] = other[key] + # Make progressively weaker assumptions about "other" + if hasattr(other, 'iteritems'): # iteritems saves memory and lookups + for k, v in other.iteritems(): + self[k] = v + elif hasattr(other, '__iter__'): # iter saves memory + for k in other: + self[k] = other[k] + else: + for k in other.keys(): + self[k] = other[k] def get(self, key, default=None): - if key in self: + try: return self[key] - return default + except KeyError: + return default def __repr__(self): - return repr(dict(self.items())) + return repr(dict(self.iteritems())) + def __cmp__(self, other): + if isinstance(other, DictMixin): + other = dict(other.iteritems()) + return cmp(dict(self.iteritems()), other) + def __len__(self): + return len(self.keys()) |