bpo-36059: Update OrderedDict() docs to reflect that regular dicts ar… · python/cpython@3006059
@@ -887,7 +887,7 @@ field names, the method and attribute names start with an underscore.
887887888888.. method:: somenamedtuple._asdict()
889889890- Return a new :class:`OrderedDict` which maps field names to their corresponding
890+ Return a new :class:`dict` which maps field names to their corresponding
891891 values:
892892893893 .. doctest::
@@ -1017,17 +1017,41 @@ customize a prototype instance:
10171017:class:`OrderedDict` objects
10181018----------------------------
101910191020-Ordered dictionaries are just like regular dictionaries but they remember the
1021-order that items were inserted. When iterating over an ordered dictionary,
1022-the items are returned in the order their keys were first added.
1020+Ordered dictionaries are just like regular dictionaries but have some extra
1021+capabilities relating to ordering operations. They have become less
1022+important now that the built-in :class:`dict` class gained the ability
1023+to remember insertion order (this new behavior became guaranteed in
1024+Python 3.7).
1025+1026+Some differences from :class:`dict` still remain:
1027+1028+* The regular :class:`dict` was designed to be very good at mapping
1029+ operations. Tracking insertion order was secondary.
1030+1031+* The :class:`OrderedDict` was designed to be good at reordering operations.
1032+ Space efficiency, iteration speed, and the performance of update
1033+ operations were secondary.
1034+1035+* Algorithmically, :class:`OrderedDict` can handle frequent reordering
1036+ operations better than :class:`dict`. This makes it suitable for tracking
1037+ recent accesses (for example in an `LRU cache
1038+<https://medium.com/@krishankantsinghal/my-first-blog-on-medium-583159139237>`_).
1039+1040+* The equality operation for :class:`OrderedDict` checks for matching order.
1041+1042+* The :meth:`popitem` method of :class:`OrderedDict` has a different
1043+ signature. It accepts an optional argument to specify which item is popped.
1044+1045+* :class:`OrderedDict` has a :meth:`move_to_end` method to
1046+ efficiently reposition an element to an endpoint.
1047+1048+* Until Python 3.8, :class:`dict` lacked a :meth:`__reversed__` method.
1049+1023105010241051.. class:: OrderedDict([items])
102510521026- Return an instance of a dict subclass, supporting the usual :class:`dict`
1027- methods. An *OrderedDict* is a dict that remembers the order that keys
1028- were first inserted. If a new entry overwrites an existing entry, the
1029- original insertion position is left unchanged. Deleting an entry and
1030- reinserting it will move it to the end.
1053+ Return an instance of a :class:`dict` subclass that has methods
1054+ specialized for rearranging dictionary order.
1031105510321056 .. versionadded:: 3.1
10331057@@ -1077,29 +1101,7 @@ anywhere a regular dictionary is used.
10771101:class:`OrderedDict` Examples and Recipes
10781102^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
107911031080-Since an ordered dictionary remembers its insertion order, it can be used
1081-in conjunction with sorting to make a sorted dictionary::
1082-1083- >>> # regular unsorted dictionary
1084- >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
1085-1086- >>> # dictionary sorted by key
1087- >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
1088- OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
1089-1090- >>> # dictionary sorted by value
1091- >>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
1092- OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
1093-1094- >>> # dictionary sorted by length of the key string
1095- >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
1096- OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
1097-1098-The new sorted dictionaries maintain their sort order when entries
1099-are deleted. But when new keys are added, the keys are appended
1100-to the end and the sort is not maintained.
1101-1102-It is also straight-forward to create an ordered dictionary variant
1104+It is straightforward to create an ordered dictionary variant
11031105that remembers the order the keys were *last* inserted.
11041106If a new entry overwrites an existing entry, the
11051107original insertion position is changed and moved to the end::
@@ -1108,21 +1110,29 @@ original insertion position is changed and moved to the end::
11081110 'Store items in the order the keys were last added'
1109111111101112 def __setitem__(self, key, value):
1111- if key in self:
1112- del self[key]
1113- OrderedDict.__setitem__(self, key, value)
1113+ super().__setitem__(key, value)
1114+ super().move_to_end(key)
111411151115-An ordered dictionary can be combined with the :class:`Counter` class
1116-so that the counter remembers the order elements are first encountered::
1116+An :class:`OrderedDict` would also be useful for implementing
1117+variants of :func:`functools.lru_cache`::
111711181118- class OrderedCounter(Counter, OrderedDict):
1119- 'Counter that remembers the order elements are first encountered'
1119+ class LRU(OrderedDict):
1120+ 'Limit size, evicting the least recently looked-up key when full'
112011211121- def __repr__(self):
1122- return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
1122+ def __init__(self, maxsize=128, *args, **kwds):
1123+ self.maxsize = maxsize
1124+ super().__init__(*args, **kwds)
112311251124- def __reduce__(self):
1125- return self.__class__, (OrderedDict(self),)
1126+ def __getitem__(self, key):
1127+ value = super().__getitem__(key)
1128+ self.move_to_end(key)
1129+ return value
1130+1131+ def __setitem__(self, key, value):
1132+ super().__setitem__(key, value)
1133+ if len(self) > self.maxsize:
1134+ oldest = next(iter(self))
1135+ del self[oldest]
112611361127113711281138:class:`UserDict` objects