According to PEP 468:
Starting in version 3.6 Python will preserve the order of keyword arguments as passed to a function. To accomplish this the coll
Regardless of what an “ordered mapping” means, as long as it’s not necessarily OrderedDict
, OrderedDict
’s ==
won’t take into account its order. Docs:
Equality tests between
OrderedDict
objects are order-sensitive and are implemented aslist(od1.items())==list(od2.items())
. Equality tests betweenOrderedDict
objects and otherMapping
objects are order-insensitive like regular dictionaries. This allowsOrderedDict
objects to be substituted anywhere a regular dictionary is used.
Just to add, if you do want to make this check (without relying on an implementation detail (which even then, won't be in python 3.7)), just do
from collections import OrderedDict
>>> data = OrderedDict(zip('xy', 'xy'))
>>> def foo(**kwargs):
... return OrderedDict(kwargs) == data
since this is guaranteed to be True.
The answer to your first 'why' is because this feature is implemented by using a plain dict
in CPython. As @Ryan's answer points out, this means that comparisons won't be order-sensitive.
The second 'why' here is why this doesn't use an OrderedDict
.
Using an OrderedDict
was the initial plan as stated in the first draft of PEP 486. The idea, as stated in this reply, was to collect some perf data to show the effect of plugging in the OrderedDict
since this was a point of contention when the idea was floated around before. The author of the PEP even alluded to the order preserving dict being another option in the final reply on that thread.
After that, the conversation on the topic seems to have died down until Python 3.6 came along. When the new dict came, it had the nice side-effect of just implementing PEP 486 out of the box (as this Python-dev thread states). The specific message in that thread also states how the author wanted the term OrderedDict
to be changed to Ordered Mapping. (This is also when a new commit on PEP 468, after the initial one, was made)
As far as I can tell, this rewording was done in order to allow other implementations to provide this feature as they see fit. CPython and PyPy already had a dict that easily implemented PEP 468, other implementations might opt for an OrderedDict
, others could go for another form of an ordered mapping.
That does open the door for a problem, though. It does mean that, theoretically, in an implementation of Python 3.6 with an OrderedDict
as the structure implementing this feature, the comparison would be order-sensitive while in others (CPython) it wouldn't. (In Python 3.7, all dict
s are required to be insertion-ordered so this point is probably moot since all implementations would use it for **kwargs
)
Though it does seem like an issue, it really isn't. As @user2357112 pointed out, there's no guarantee on ==
. PEP 468 only guarantees order. As far as I can tell, ==
is basically implementation defined.
In short, it compares equal in CPython because kwargs
in CPython is a dict
and it's a dict
because after 3.6
the whole thing just worked.
"Ordered mapping" only means the mapping has to preserve order. It doesn't mean that order has to be part of the mapping's ==
relation.
The purpose of PEP 468 is just to preserve the ordering information. Having order be part of ==
would produce backward incompatibility without any real benefit to any of the use cases that motivated PEP 468. Using OrderedDict
would also be more expensive (since OrderedDict
still maintains its own separate linked list to track order, and it can't abandon that linked list without sacrificing big-O efficiency in popitem
and move_to_end
).