sorteddict.py revision 7503:37da2c208f5f
1# Copyright (c) 2006-2009 Nathan Binkert <nate@binkert.org> 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution; 11# neither the name of the copyright holders nor the names of its 12# contributors may be used to endorse or promote products derived from 13# this software without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27class SortedDict(dict): 28 def _get_sorted(self): 29 return getattr(self, '_sorted', sorted) 30 def _set_sorted(self, val): 31 self._sorted = val 32 self._del_keys() 33 sorted = property(_get_sorted, _set_sorted) 34 35 @property 36 def _keys(self): 37 try: 38 return self._sorted_keys 39 except AttributeError: 40 _sorted_keys = self.sorted(dict.iterkeys(self)) 41 self._sorted_keys = _sorted_keys 42 return _sorted_keys 43 44 def _del_keys(self): 45 try: 46 del self._sorted_keys 47 except AttributeError: 48 pass 49 50 def __repr__(self): 51 return 'SortedDict({%s})' % ', '.join('%r: %r' % item 52 for item in self.iteritems()) 53 def __setitem__(self, key, item): 54 dict.__setitem__(self, key, item) 55 self._del_keys() 56 57 def __delitem__(self, key): 58 dict.__delitem__(self, key) 59 self._del_keys() 60 61 def clear(self): 62 self.data.clear() 63 self._del_keys() 64 65 def copy(self): 66 t = type(self) 67 return t(self) 68 69 def keys(self): 70 return self._keys[:] 71 72 def values(self): 73 return list(self.itervalues()) 74 75 def items(self): 76 return list(self.iteritems()) 77 78 def iterkeys(self): 79 return iter(self._keys) 80 81 def itervalues(self): 82 for k in self._keys: 83 yield self[k] 84 85 def iteritems(self): 86 for k in self._keys: 87 yield k, self[k] 88 89 def update(self, *args, **kwargs): 90 dict.update(self, *args, **kwargs) 91 self._del_keys() 92 93 def setdefault(self, key, _failobj=None): 94 try: 95 return self[key] 96 except KeyError: 97 self[key] = _failobj 98 99 def pop(self, key, *args): 100 try: 101 dict.pop(self, key) 102 self._del_keys() 103 except KeyError: 104 if not args: 105 raise 106 return args[0] 107 108 def popitem(self): 109 try: 110 key = self._keys[0] 111 self._del_keys() 112 except IndexError: 113 raise KeyError('popitem(): dictionary is empty') 114 else: 115 return key, dict.pop(self, key) 116 117 @classmethod 118 def fromkeys(cls, seq, value=None): 119 d = cls() 120 for key in seq: 121 d[key] = value 122 return d 123 124if __name__ == '__main__': 125 def display(d): 126 print d 127 print d.keys() 128 print list(d.iterkeys()) 129 print d.values() 130 print list(d.itervalues()) 131 print d.items() 132 print list(d.iteritems()) 133 134 d = SortedDict(x=24,e=5,j=4,b=2,z=26,d=4) 135 display(d) 136 137 print 'popitem', d.popitem() 138 display(d) 139 140 print 'pop j' 141 d.pop('j') 142 display(d) 143 144 d.setdefault('a', 1) 145 d.setdefault('g', 7) 146 d.setdefault('_') 147 display(d) 148 149 d.update({'b' : 2, 'h' : 8}) 150 display(d) 151 152 del d['x'] 153 display(d) 154 d['y'] = 26 155 display(d) 156 157 print `d` 158 159 print d.copy() 160