More small edits.

This commit is contained in:
Raymond Hettinger 2009-02-27 22:01:24 +00:00
parent 12360f5946
commit d1f883f6a1
1 changed files with 22 additions and 27 deletions

View File

@ -122,18 +122,12 @@ Questions and Answers
What happens if an existing key is reassigned?
The key is not moved but assigned a new value in place. This is
consistent with existing implementations and allows subclasses to
change the behavior easily::
class moving_odict(collections.odict):
def __setitem__(self, key, value):
self.pop(key, None)
collections.odict.__setitem__(self, key, value)
consistent with existing implementations.
What happens if keys appear multiple times in the list passed to the
constructor?
The same as for regular dicts: The latter item overrides the
The same as for regular dicts -- the latter item overrides the
former. This has the side-effect that the position of the first
key is used because only the value is actually overwritten::
@ -145,17 +139,17 @@ constructor?
Is the ordered dict a dict subclass? Why?
Yes. Like ``defaultdict``, ``odict`` subclasses ``dict``.
Being a dict subclass confers speed upon methods that aren't overridden
like ``__getitem__`` and ``__len__``. Also, being a dict gives the
most utility with tools that were expecting regular dicts (like the
json module).
Yes. Like ``defaultdict``, an ordered dictionary `` subclasses ``dict``.
Being a dict subclass make some of the methods faster (like
``__getitem__`` and ``__len__``). More importantly, being a dict
subclass lets ordered dictionaries be usable with tools like json that
insist on having dict inputs by testing isinstance(d, dict).
Do any limitations arise from subclassing dict?
Yes. Since the API for dicts is different in Py2.x and Py3.x, the
odict API must also be different (i.e. Py2.6 needs to override
iterkeys, itervalues, and iteritems).
odict API must also be different. So, the Py2.7 version will need
to override iterkeys, itervalues, and iteritems.
Does ``odict.popitem()`` return a particular key/value pair?
@ -164,22 +158,21 @@ Does ``odict.popitem()`` return a particular key/value pair?
exhibited by traditional push/pop pairs. It is semantically
equivalent to ``k=list(od)[-1]; v=od[k]; del od[k]; return (k,v)``.
The actual implementation is more efficient and pops directly
off of a sorted list of keys.
from a sorted list of keys.
Does odict support indexing, slicing, and whatnot?
As a matter of fact, ``odict`` does not implement the ``Sequence``
interface. Rather, it is a ``MutableMapping`` that remembers
the order of key insertion. The only sequence-like addition is
automatic support for ``reversed``.
support for ``reversed``.
Does odict support alternate sort orders such as alphabetical?
No. Those wanting different sort orders really need to be using another
technique. The odict is all about recording insertion order. If any
other order is of interest, then another structure (like an in-memory
dbm) is likely a better fit. It would be a mistake to try to be all
things to all users.
dbm) is likely a better fit.
How well does odict work with the json module, PyYAML, and ConfigParser?
@ -213,7 +206,7 @@ How well does odict work with the json module, PyYAML, and ConfigParser?
>>> yaml.load(ytext)
OrderedDict({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5})
For the ConfigParser module, round-tripping is problem free. Custom
For the ConfigParser module, round-tripping is also problem free. Custom
dicts were added in Py2.6 specifically to support ordered dictionaries::
>>> config = ConfigParser(dict_type=OrderedDict)
@ -224,21 +217,23 @@ How well does odict work with the json module, PyYAML, and ConfigParser?
How does odict handle equality testing?
Being a dict, one might expect equality tests to not care about order. For
an odict to dict comparison, this would be a necessity and it's probably
an odict-to-dict comparison, this would be a necessity and it's probably
not wise to silently switch comparison modes based on the input types.
Also, some third-party tools that expect dict inputs may also expect the
comparison to not care about order. Accordingly, we decided to punt and
let the usual dict equality testing run without reference to internal
ordering. This should be documented clearly since different people will
have different expectations. If a use case does arise, it's not hard to
explicitly craft an order based comparison:
``list(od1.items())==list(od2.items())``.
have different expectations. If a use case does arise, it's not hard for
a user explicitly craft an order based comparison::
# Explict order-sensitive comparison
>>> list(od1.items())==list(od2.items())
What are the trade-offs of the possible underlying data structures?
* Keeping a sorted list of keys is very fast for all operations except
__delitem__() which becomes an O(n) exercise. This structure leads to
very simple code and little wasted space.
* Keeping a sorted list of keys is fast for all operations except
__delitem__() which becomes an O(n) exercise. This data structure leads
to very simple code and little wasted space.
* Keeping a separate dictionary to record insertion sequence numbers makes
the code a little bit more complex. All of the basic operations are O(1)