175 lines · 5.6 KB · Python
RawDownload
"""A more or less complete user-defined wrapper around dictionary objects.""" class UserDict:    def __init__(self, dict=None, **kwargs):        self.data = {}        if dict is not None:            self.update(dict)        if len(kwargs):            self.update(kwargs)    def __repr__(self): return repr(self.data)    def __cmp__(self, dict):        if isinstance(dict, UserDict):            return cmp(self.data, dict.data)        else:            return cmp(self.data, dict)    def __len__(self): return len(self.data)    def __getitem__(self, key):        if key in self.data:            return self.data[key]        if hasattr(self.__class__, "__missing__"):            return self.__class__.__missing__(self, key)        raise KeyError(key)    def __setitem__(self, key, item): self.data[key] = item    def __delitem__(self, key): del self.data[key]    def clear(self): self.data.clear()    def copy(self):        if self.__class__ is UserDict:            return UserDict(self.data.copy())        import copy        data = self.data        try:            self.data = {}            c = copy.copy(self)        finally:            self.data = data        c.update(self)        return c    def keys(self): return self.data.keys()    def items(self): return self.data.items()    def iteritems(self): return self.data.iteritems()    def iterkeys(self): return self.data.iterkeys()    def itervalues(self): return self.data.itervalues()    def values(self): return self.data.values()    def has_key(self, key): return self.data.has_key(key)    def update(self, dict=None, **kwargs):        if dict is None:            pass        elif isinstance(dict, UserDict):            self.data.update(dict.data)        elif isinstance(dict, type({})) or not hasattr(dict, 'items'):            self.data.update(dict)        else:            for k, v in dict.items():                self[k] = v        if len(kwargs):            self.data.update(kwargs)    def get(self, key, failobj=None):        if not self.has_key(key):            return failobj        return self[key]    def setdefault(self, key, failobj=None):        if not self.has_key(key):            self[key] = failobj        return self[key]    def pop(self, key, *args):        return self.data.pop(key, *args)    def popitem(self):        return self.data.popitem()    def __contains__(self, key):        return key in self.data    @classmethod    def fromkeys(cls, iterable, value=None):        d = cls()        for key in iterable:            d[key] = value        return d class IterableUserDict(UserDict):    def __iter__(self):        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. Without knowledge of the subclass constructor, the mixin    # does not define __init__() or copy().  In addition to the four base    # methods, progressively more efficiency comes with defining    # __contains__(), __iter__(), and iteritems().     # 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]        except KeyError:            return False        return True    def __contains__(self, key):        return self.has_key(key)     # third level takes advantage of second level definitions    def iteritems(self):        for k in self:            yield (k, self[k])    def iterkeys(self):        return self.__iter__()     # fourth level uses definitions from lower levels    def itervalues(self):        for _, v in self.iteritems():            yield v    def values(self):        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=None):        try:            return self[key]        except KeyError:            self[key] = default        return default    def pop(self, key, *args):        if len(args) > 1:            raise TypeError, "pop expected at most 2 arguments, got "\                              + repr(1 + len(args))        try:            value = self[key]        except KeyError:            if args:                return args[0]            raise        del self[key]        return value    def popitem(self):        try:            k, v = self.iteritems().next()        except StopIteration:            raise KeyError, 'container is empty'        del self[k]        return (k, v)    def update(self, other=None, **kwargs):        # Make progressively weaker assumptions about "other"        if other is None:            pass        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups            for k, v in other.iteritems():                self[k] = v        elif hasattr(other, 'keys'):            for k in other.keys():                self[k] = other[k]        else:            for k, v in other:                self[k] = v        if kwargs:            self.update(kwargs)    def get(self, key, default=None):        try:            return self[key]        except KeyError:            return default    def __repr__(self):        return repr(dict(self.iteritems()))    def __cmp__(self, other):        if other is None:            return 1        if isinstance(other, DictMixin):            other = dict(other.iteritems())        return cmp(dict(self.iteritems()), other)    def __len__(self):        return len(self.keys())