Why does the ** kwargs match against another ordered OrderedDict?

According to PEP 468 :

Since version 3.6 Python will preserve the order of the keyword arguments passed to the function. For this, the collected kwargs will now be sorted display . Note that this does not necessarily mean OrderedDict

.

In this case, why is it ordered comparison does not account for the comparison of equality with the canonical ordered Python type display collections.OrderedDict

:

>>> from collections import OrderedDict
>>> data = OrderedDict(zip('xy', 'xy'))
>>> def foo(**kwargs):
...     return kwargs == data
... 
>>> foo(x='x', y='y')  # expected result: True
True
>>> foo(y='y', x='x')  # expected result: False
True

      

Although the iteration order is now preserved, kwargs

it seems to behave just like a normal dict for comparisons. Python has a C implemented ordered dict since 3.5 , so it could possibly have been used directly (or if performance is still a concern, a faster implementation using a thin subclass 3.6 compact dict).

Why is the ordered collation obtained by the function not ordered when comparing comparisons?

+11


source to share


4 answers


The answer to your first "why" is that this feature is implemented using a simple dict

CPython. As @Ryan points out, this means comparisons will not be order sensitive.

Second "why" that's why it doesn't use OrderedDict



...

Using OrderedDict



was the initial blueprint as stated in the first draft of PEP 486. The idea, as an iteration of this answer , was to collect some primary data to show the effect of connecting toOrderedDict



as it was a controversial point where the idea was posted around earlier. The author of the PEP even referred to the order retaining the dict being another option in the final answer in this thread.

After that, the conversation on the topic seemed to have died away until Python 3.6 came along. When the new dictar came out, it had a nice side effect of implementing PEP 486 out of the box (as is the state of the Python-dev thread ). The specific post in this thread also indicates how the author wanted the termOrderedDict



was changed to ordered collation. (This is also when a new commit was made on PEP 468 , after the original)

As far as I can tell, this entry was made so that other implementations can provide this functionality as they see fit. CPython and PyPy already had a dict that easily implemented PEP 468, other implementations might chooseOrderedDict



, others might go for another form of ordered display.

However, this opens the door to a problem. This means that in theory, when implementing Python 3.6 withOrderedDict



as a structure that implements this function the comparison will be order sensitive, while others (CPython) will not. (In Python 3.7, everything dict

must be ordered in order, so this point is likely to be controversial since all implementations will use it for **kwargs

)

While this sounds like a problem, it really isn't. As @ user2357112 pointed out, ==

there is no guarantee. PEP 468 only guarantees ordering. As far as I can tell, ==

is largely implementation-defined.


In short, it compares the value in CPython, because kwargs

in CPython it is dict

, and a dict

, because after 3.6

that it just worked.

+5


source


Whatever "ordered collation" means, if not necessary OrderedDict

, OrderedDict

s ==

ignore its order. Documents:



Equality tests between objects are OrderedDict

order sensitive and are implemented as list(od1.items())==list(od2.items())

. Equality tests between objects OrderedDict

and other objects Mapping

are order-independent like regular dictionaries.
This allows objects to be replaced OrderedDict

wherever a regular dictionary is used.

+13


source


"Ordered mapping" means that the display must preserve order. This does not mean that the order should be part of the display relationship ==

.

The purpose of PEP 468 is to preserve order information. Ordering to be a part ==

would result in lagging incompatibilities with no real benefit for any of the use cases that motivated PEP 468. The use would OrderedDict

also be more costly (as OrderedDict

it still keeps its own separate linked list to keep track of and can't give up on it) linked list without sacrificing much O's efficiency in popitem

and move_to_end

).

+9


source


Just add if you want to do 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.

0


source







All Articles