Update PEP based on latest version of recipe, based on integration testing, and based on newsgroup feedback.
This commit is contained in:
parent
879ca8008b
commit
4715116df7
73
pep-0372.txt
73
pep-0372.txt
|
@ -143,22 +143,19 @@ constructor?
|
||||||
This behavior is consistent with existing implementations in
|
This behavior is consistent with existing implementations in
|
||||||
Python, the PHP array and the hashmap in Ruby 1.9.
|
Python, the PHP array and the hashmap in Ruby 1.9.
|
||||||
|
|
||||||
Why is there no ``odict.insert()``?
|
Is the ordered dict a dict subclass? Why?
|
||||||
|
|
||||||
There are few situations where you really want to insert a key at
|
|
||||||
a specified index. To avoid API complication, the proposed
|
|
||||||
solution for this situation is creating a list of items,
|
|
||||||
manipulating that and converting it back into an odict:
|
|
||||||
|
|
||||||
>>> d = odict([('a', 42), ('b', 23), ('c', 19)])
|
|
||||||
>>> l = d.items()
|
|
||||||
>>> l.insert(1, ('x', 0))
|
|
||||||
>>> odict(l)
|
|
||||||
collections.odict([('a', 42), ('x', 0), ('b', 23), ('c', 19)])
|
|
||||||
|
|
||||||
Is the ordered dict a dict subclass?
|
|
||||||
|
|
||||||
Yes. Like ``defaultdict``, ``odict`` subclasses ``dict``.
|
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).
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
Does ``odict.popitem()`` return a particular key/value pair?
|
Does ``odict.popitem()`` return a particular key/value pair?
|
||||||
|
|
||||||
|
@ -166,8 +163,8 @@ Does ``odict.popitem()`` return a particular key/value pair?
|
||||||
corresponding value. This corresponds to the usual LIFO behavior
|
corresponding value. This corresponds to the usual LIFO behavior
|
||||||
exhibited by traditional push/pop pairs. It is semantically
|
exhibited by traditional push/pop pairs. It is semantically
|
||||||
equivalent to ``k=list(od)[-1]; v=od[k]; del od[k]; return (k,v)``.
|
equivalent to ``k=list(od)[-1]; v=od[k]; del od[k]; return (k,v)``.
|
||||||
The actual implementation is more efficient. It is O(n log n)
|
The actual implementation is more efficient and pops directly
|
||||||
on the first call, any successive calls are O(1).
|
off of a sorted list of keys.
|
||||||
|
|
||||||
Does odict support indexing, slicing, and whatnot?
|
Does odict support indexing, slicing, and whatnot?
|
||||||
|
|
||||||
|
@ -184,6 +181,50 @@ Does odict support alternate sort orders such as alphabetical?
|
||||||
dbm) is likely a better fit. It would be a mistake to try to be all
|
dbm) is likely a better fit. It would be a mistake to try to be all
|
||||||
things to all users.
|
things to all users.
|
||||||
|
|
||||||
|
How well does odict work with the json module and PyYAML?
|
||||||
|
|
||||||
|
For json, the good news is that json's encoder respects odict's iteration order:
|
||||||
|
|
||||||
|
>>> items = [('one', 1), ('two', 2), ('three',3), ('four',4), ('five',5)]
|
||||||
|
>>> json.dumps(OrderedDict(items))
|
||||||
|
'{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}'
|
||||||
|
|
||||||
|
The bad news is that the object_hook for json decoders will pass in an
|
||||||
|
already built dictionary so that the order is lost before the object
|
||||||
|
hook sees it:
|
||||||
|
|
||||||
|
>>> jtext = '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}'
|
||||||
|
>>> json.loads(jtext, object_hook=OrderedDict)
|
||||||
|
OrderedDict({u'four': 4, u'three': 3, u'five': 5, u'two': 2, u'one': 1})
|
||||||
|
|
||||||
|
For PyYAML, a full round-trip is problem free:
|
||||||
|
|
||||||
|
>>> ytext = yaml.dump(OrderedDict(items))
|
||||||
|
>>> print ytext
|
||||||
|
!!python/object/apply:collections.OrderedDict
|
||||||
|
- - [one, 1]
|
||||||
|
- [two, 2]
|
||||||
|
- [three, 3]
|
||||||
|
- [four, 4]
|
||||||
|
- [five, 5]
|
||||||
|
|
||||||
|
>>> yaml.load(ytext)
|
||||||
|
OrderedDict({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5})
|
||||||
|
|
||||||
|
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
|
||||||
|
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())``.
|
||||||
|
|
||||||
|
|
||||||
Reference Implementation
|
Reference Implementation
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue