diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/UserDict.py | 61 | ||||
-rw-r--r-- | Lib/test/test_userdict.py | 11 |
2 files changed, 43 insertions, 29 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()) diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py index 6f3b853..a59419d 100644 --- a/Lib/test/test_userdict.py +++ b/Lib/test/test_userdict.py @@ -210,9 +210,8 @@ else: s.update({10: 'ten', 20:'twenty'}) # update verify(s[10]=='ten' and s[20]=='twenty') - - - - - - +verify(s == {10: 'ten', 20:'twenty'}) # cmp +t = SeqDict() +t[20] = 'twenty' +t[10] = 'ten' +verify(s == t) |