Dictionary that remembers insertion order
| 87 | __slots__ = 'prev', 'next', 'key', '__weakref__' |
| 88 | |
| 89 | class OrderedDict(dict): |
| 90 | 'Dictionary that remembers insertion order' |
| 91 | # An inherited dict maps keys to values. |
| 92 | # The inherited dict provides __getitem__, __len__, __contains__, and get. |
| 93 | # The remaining methods are order-aware. |
| 94 | # Big-O running times for all methods are the same as regular dictionaries. |
| 95 | |
| 96 | # The internal self.__map dict maps keys to links in a doubly linked list. |
| 97 | # The circular doubly linked list starts and ends with a sentinel element. |
| 98 | # The sentinel element never gets deleted (this simplifies the algorithm). |
| 99 | # The sentinel is in self.__hardroot with a weakref proxy in self.__root. |
| 100 | # The prev links are weakref proxies (to prevent circular references). |
| 101 | # Individual links are kept alive by the hard reference in self.__map. |
| 102 | # Those hard references disappear when a key is deleted from an OrderedDict. |
| 103 | |
| 104 | def __new__(cls, /, *args, **kwds): |
| 105 | "Create the ordered dict object and set up the underlying structures." |
| 106 | self = dict.__new__(cls) |
| 107 | self.__hardroot = _Link() |
| 108 | self.__root = root = _proxy(self.__hardroot) |
| 109 | root.prev = root.next = root |
| 110 | self.__map = {} |
| 111 | return self |
| 112 | |
| 113 | def __init__(self, other=(), /, **kwds): |
| 114 | '''Initialize an ordered dictionary. The signature is the same as |
| 115 | regular dictionaries. Keyword argument order is preserved. |
| 116 | ''' |
| 117 | self.__update(other, **kwds) |
| 118 | |
| 119 | def __setitem__(self, key, value, |
| 120 | dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link): |
| 121 | 'od.__setitem__(i, y) <==> od[i]=y' |
| 122 | # Setting a new item creates a new link at the end of the linked list, |
| 123 | # and the inherited dictionary is updated with the new key/value pair. |
| 124 | if key not in self: |
| 125 | self.__map[key] = link = Link() |
| 126 | root = self.__root |
| 127 | last = root.prev |
| 128 | link.prev, link.next, link.key = last, root, key |
| 129 | last.next = link |
| 130 | root.prev = proxy(link) |
| 131 | dict_setitem(self, key, value) |
| 132 | |
| 133 | def __delitem__(self, key, dict_delitem=dict.__delitem__): |
| 134 | 'od.__delitem__(y) <==> del od[y]' |
| 135 | # Deleting an existing item uses self.__map to find the link which gets |
| 136 | # removed by updating the links in the predecessor and successor nodes. |
| 137 | dict_delitem(self, key) |
| 138 | link = self.__map.pop(key) |
| 139 | link_prev = link.prev |
| 140 | link_next = link.next |
| 141 | link_prev.next = link_next |
| 142 | link_next.prev = link_prev |
| 143 | link.prev = None |
| 144 | link.next = None |
| 145 | |
| 146 | def __iter__(self): |
no outgoing calls
searching dependent graphs…