class odict(dict): def __init__(self, d={}): self._keys = d.keys() dict.__init__(self, d) def __delitem__(self, key): dict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): dict.__setitem__(self, key, item) # a peculiar sharp edge from copy.deepcopy # we'll have our set item called without __init__ if not hasattr(self, '_keys'): self._keys = [key,] if key not in self._keys: self._keys.append(key) def clear(self): dict.clear(self) self._keys = [] def items(self): items = [] for i in self._keys: items.append(i, self[i]) return items def keys(self): return self._keys def popitem(self): if len(self._keys) == 0: raise KeyError('dictionary is empty') else: key = self._keys[-1] val = self[key] del self[key] return key, val def setdefault(self, key, failobj = None): dict.setdefault(self, key, failobj) if key not in self._keys: self._keys.append(key) def update(self, d): for key in d.keys(): if not self.has_key(key): self._keys.append(key) dict.update(self, d) def values(self): v = [] for i in self._keys: v.append(self[i]) return v def move(self, key, index): """ Move the specified to key to *before* the specified index. """ try: cur = self._keys.index(key) except ValueError: raise KeyError(key) self._keys.insert(index, key) # this may have shifted the position of cur, if it is after index if cur >= index: cur = cur + 1 del self._keys[cur] def index(self, key): if not self.has_key(key): raise KeyError(key) return self._keys.index(key) def __iter__(self): for k in self._keys: yield k