1
# Copyright (c) 2009 Raymond Hettinger
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:
11
# The above copyright notice and this permission notice shall be
12
# included in all copies or substantial portions of the Software.
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.
23
from UserDict import DictMixin
25
class OrderedDict(dict, DictMixin):
27
def __init__(self, *args, **kwds):
29
raise TypeError('expected at most 1 arguments, got %d' % len(args))
32
except AttributeError:
34
self.update(*args, **kwds)
38
end += [None, end, end] # sentinel node for doubly linked list
39
self.__map = {} # key --> [key, prev, next]
42
def __setitem__(self, key, value):
46
curr[2] = end[1] = self.__map[key] = [key, curr, end]
47
dict.__setitem__(self, key, value)
49
def __delitem__(self, key):
50
dict.__delitem__(self, key)
51
key, prev, next = self.__map.pop(key)
58
while curr is not end:
62
def __reversed__(self):
65
while curr is not end:
69
def popitem(self, last=True):
71
raise KeyError('dictionary is empty')
73
key = reversed(self).next()
75
key = iter(self).next()
80
items = [[k, self[k]] for k in self]
81
tmp = self.__map, self.__end
82
del self.__map, self.__end
83
inst_dict = vars(self).copy()
84
self.__map, self.__end = tmp
86
return (self.__class__, (items,), inst_dict)
87
return self.__class__, (items,)
92
setdefault = DictMixin.setdefault
93
update = DictMixin.update
95
values = DictMixin.values
96
items = DictMixin.items
97
iterkeys = DictMixin.iterkeys
98
itervalues = DictMixin.itervalues
99
iteritems = DictMixin.iteritems
103
return '%s()' % (self.__class__.__name__,)
104
return '%s(%r)' % (self.__class__.__name__, self.items())
107
return self.__class__(self)
110
def fromkeys(cls, iterable, value=None):
116
def __eq__(self, other):
117
if isinstance(other, OrderedDict):
118
if len(self) != len(other):
120
for p, q in zip(self.items(), other.items()):
124
return dict.__eq__(self, other)
126
def __ne__(self, other):
127
return not self == other