summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/UserDict.py61
-rw-r--r--Lib/test/test_userdict.py11
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)