UserDict.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """A more or less complete user-defined wrapper around dictionary objects."""
  2. class UserDict:
  3. def __init__(self, dict=None, **kwargs):
  4. self.data = {}
  5. if dict is not None:
  6. self.update(dict)
  7. if len(kwargs):
  8. self.update(kwargs)
  9. def __repr__(self): return repr(self.data)
  10. def __cmp__(self, dict):
  11. if isinstance(dict, UserDict):
  12. return cmp(self.data, dict.data)
  13. else:
  14. return cmp(self.data, dict)
  15. def __len__(self): return len(self.data)
  16. def __getitem__(self, key): return self.data[key]
  17. def __setitem__(self, key, item): self.data[key] = item
  18. def __delitem__(self, key): del self.data[key]
  19. def clear(self): self.data.clear()
  20. def copy(self):
  21. if self.__class__ is UserDict:
  22. return UserDict(self.data.copy())
  23. import copy
  24. data = self.data
  25. try:
  26. self.data = {}
  27. c = copy.copy(self)
  28. finally:
  29. self.data = data
  30. c.update(self)
  31. return c
  32. def keys(self): return self.data.keys()
  33. def items(self): return self.data.items()
  34. def iteritems(self): return self.data.iteritems()
  35. def iterkeys(self): return self.data.iterkeys()
  36. def itervalues(self): return self.data.itervalues()
  37. def values(self): return self.data.values()
  38. def has_key(self, key): return self.data.has_key(key)
  39. def update(self, dict=None, **kwargs):
  40. if dict is None:
  41. pass
  42. elif isinstance(dict, UserDict):
  43. self.data.update(dict.data)
  44. elif isinstance(dict, type({})) or not hasattr(dict, 'items'):
  45. self.data.update(dict)
  46. else:
  47. for k, v in dict.items():
  48. self[k] = v
  49. if len(kwargs):
  50. self.data.update(kwargs)
  51. def get(self, key, failobj=None):
  52. if not self.has_key(key):
  53. return failobj
  54. return self[key]
  55. def setdefault(self, key, failobj=None):
  56. if not self.has_key(key):
  57. self[key] = failobj
  58. return self[key]
  59. def pop(self, key, *args):
  60. return self.data.pop(key, *args)
  61. def popitem(self):
  62. return self.data.popitem()
  63. def __contains__(self, key):
  64. return key in self.data
  65. def fromkeys(cls, iterable, value=None):
  66. d = cls()
  67. for key in iterable:
  68. d[key] = value
  69. return d
  70. fromkeys = classmethod(fromkeys)
  71. class IterableUserDict(UserDict):
  72. def __iter__(self):
  73. return iter(self.data)
  74. class DictMixin:
  75. # Mixin defining all dictionary methods for classes that already have
  76. # a minimum dictionary interface including getitem, setitem, delitem,
  77. # and keys. Without knowledge of the subclass constructor, the mixin
  78. # does not define __init__() or copy(). In addition to the four base
  79. # methods, progressively more efficiency comes with defining
  80. # __contains__(), __iter__(), and iteritems().
  81. # second level definitions support higher levels
  82. def __iter__(self):
  83. for k in self.keys():
  84. yield k
  85. def has_key(self, key):
  86. try:
  87. value = self[key]
  88. except KeyError:
  89. return False
  90. return True
  91. def __contains__(self, key):
  92. return self.has_key(key)
  93. # third level takes advantage of second level definitions
  94. def iteritems(self):
  95. for k in self:
  96. yield (k, self[k])
  97. def iterkeys(self):
  98. return self.__iter__()
  99. # fourth level uses definitions from lower levels
  100. def itervalues(self):
  101. for _, v in self.iteritems():
  102. yield v
  103. def values(self):
  104. return [v for _, v in self.iteritems()]
  105. def items(self):
  106. return list(self.iteritems())
  107. def clear(self):
  108. for key in self.keys():
  109. del self[key]
  110. def setdefault(self, key, default=None):
  111. try:
  112. return self[key]
  113. except KeyError:
  114. self[key] = default
  115. return default
  116. def pop(self, key, *args):
  117. if len(args) > 1:
  118. raise TypeError, "pop expected at most 2 arguments, got "\
  119. + repr(1 + len(args))
  120. try:
  121. value = self[key]
  122. except KeyError:
  123. if args:
  124. return args[0]
  125. raise
  126. del self[key]
  127. return value
  128. def popitem(self):
  129. try:
  130. k, v = self.iteritems().next()
  131. except StopIteration:
  132. raise KeyError, 'container is empty'
  133. del self[k]
  134. return (k, v)
  135. def update(self, other=None, **kwargs):
  136. # Make progressively weaker assumptions about "other"
  137. if other is None:
  138. pass
  139. elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups
  140. for k, v in other.iteritems():
  141. self[k] = v
  142. elif hasattr(other, 'keys'):
  143. for k in other.keys():
  144. self[k] = other[k]
  145. else:
  146. for k, v in other:
  147. self[k] = v
  148. if kwargs:
  149. self.update(kwargs)
  150. def get(self, key, default=None):
  151. try:
  152. return self[key]
  153. except KeyError:
  154. return default
  155. def __repr__(self):
  156. return repr(dict(self.iteritems()))
  157. def __cmp__(self, other):
  158. if other is None:
  159. return 1
  160. if isinstance(other, DictMixin):
  161. other = dict(other.iteritems())
  162. return cmp(dict(self.iteritems()), other)
  163. def __len__(self):
  164. return len(self.keys())