_ordereddict.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. # Copyright (c) 2009 Raymond Hettinger
  2. #
  3. # Permission is hereby granted, free of charge, to any person
  4. # obtaining a copy of this software and associated documentation files
  5. # (the "Software"), to deal in the Software without restriction,
  6. # including without limitation the rights to use, copy, modify, merge,
  7. # publish, distribute, sublicense, and/or sell copies of the Software,
  8. # and to permit persons to whom the Software is furnished to do so,
  9. # subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be
  12. # included in all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. # OTHER DEALINGS IN THE SOFTWARE.
  22. import sys
  23. if not sys.version_info < (2, 7):
  24. from collections import OrderedDict
  25. else:
  26. from UserDict import DictMixin
  27. class OrderedDict(dict, DictMixin):
  28. def __init__(self, *args, **kwds):
  29. if len(args) > 1:
  30. raise TypeError('expected at most 1 arguments, got %d' % len(args))
  31. try:
  32. self.__end
  33. except AttributeError:
  34. self.clear()
  35. self.update(*args, **kwds)
  36. def clear(self):
  37. self.__end = end = []
  38. end += [None, end, end] # sentinel node for doubly linked list
  39. self.__map = {} # key --> [key, prev, next]
  40. dict.clear(self)
  41. def __setitem__(self, key, value):
  42. if key not in self:
  43. end = self.__end
  44. curr = end[1]
  45. curr[2] = end[1] = self.__map[key] = [key, curr, end]
  46. dict.__setitem__(self, key, value)
  47. def __delitem__(self, key):
  48. dict.__delitem__(self, key)
  49. key, prev, next_ = self.__map.pop(key)
  50. prev[2] = next_
  51. next_[1] = prev
  52. def __iter__(self):
  53. end = self.__end
  54. curr = end[2]
  55. while curr is not end:
  56. yield curr[0]
  57. curr = curr[2]
  58. def __reversed__(self):
  59. end = self.__end
  60. curr = end[1]
  61. while curr is not end:
  62. yield curr[0]
  63. curr = curr[1]
  64. def popitem(self, last=True):
  65. if not self:
  66. raise KeyError('dictionary is empty')
  67. if last:
  68. key = reversed(self).next()
  69. else:
  70. key = iter(self).next()
  71. value = self.pop(key)
  72. return key, value
  73. def __reduce__(self):
  74. items = [[k, self[k]] for k in self]
  75. tmp = self.__map, self.__end
  76. del self.__map, self.__end
  77. inst_dict = vars(self).copy()
  78. self.__map, self.__end = tmp
  79. if inst_dict:
  80. return (self.__class__, (items,), inst_dict)
  81. return self.__class__, (items,)
  82. def keys(self):
  83. return list(self)
  84. setdefault = DictMixin.setdefault
  85. update = DictMixin.update
  86. pop = DictMixin.pop
  87. values = DictMixin.values
  88. items = DictMixin.items
  89. iterkeys = DictMixin.iterkeys
  90. itervalues = DictMixin.itervalues
  91. iteritems = DictMixin.iteritems
  92. def __repr__(self):
  93. if not self:
  94. return '%s()' % (self.__class__.__name__,)
  95. return '%s(%r)' % (self.__class__.__name__, self.items())
  96. def copy(self):
  97. return self.__class__(self)
  98. @classmethod
  99. def fromkeys(cls, iterable, value=None):
  100. d = cls()
  101. for key in iterable:
  102. d[key] = value
  103. return d
  104. def __eq__(self, other):
  105. if isinstance(other, OrderedDict):
  106. if len(self) != len(other):
  107. return False
  108. for p, q in zip(self.items(), other.items()):
  109. if p != q:
  110. return False
  111. return True
  112. return dict.__eq__(self, other)
  113. def __ne__(self, other):
  114. return not self == other