Why do OrderedDict keys compare order insensitivity?

Why is the look of the OrderedDict keys compared to case insensitive?

 >>> from collections import OrderedDict >>> xy = OrderedDict([('x', None), ('y', None)]) >>> yx = OrderedDict([('y', None), ('x', None)]) >>> xy == yx False >>> xy.keys() == yx.keys() True 

In the view, the "OrderedDict" should apparently behave like an OrderedSet, but instead it behaves the same as dict.keys (ie, like a regular set ).

Same issue in python2:

 >>> xy.viewkeys() == yx.viewkeys() True 

These are different types, ( odict_keys is a subclass of dict_keys )

 >>> type(xy.keys()) odict_keys >>> type({}.keys()) dict_keys 

And a key comparison is available for customers , which they could use trivially, but, apparently, it was used only as a post-check to compare with rich experience.

Is this a design decision or a mistake? If this is a design decision, where can I find the rationale?

+12
python python-internals ordereddictionary
Dec 16 '15 at 19:35
source share
2 answers

It seems that OrderedDict delegated the implementation of various view objects into a common dict implementation; this remains true even in Python 3.5, where OrderedDict received an accelerated implementation of C ( it delegates the construction of the _PyDictView_New object and does not provide cancellation for the general representation of the rich comparison function .

In principle, OrderedDict tags OrderedDict scanned in the same order as their support for OrderedDict (because there is no cost), but for set operations, they act like set , using equality of content, subset / subset, etc.

It makes the choice to ignore ordering makes sense to some extent; for some set operations (for example, & , | , ^ ), the return value is set without order (since there is no OrderedSet , and even if it were, what order do you use for something like & , where the order may differ in each representation ?), you will get inconsistent behavior if some of the set operations were order sensitive and some were not. And it would be even stranger when two OrderedDict key OrderedDict were order sensitive, but there was no comparison of OrderedDict representations with dict representations.

As I noticed in the comments, you can easily compare the order of keys with:

 from operator import eq # Verify that keys are the same length and same set of values first for speed # The `all` check then verifies that the known identical keys appear in the # same order. xy.keys() == yx.keys() and all(map(eq, xy, yx)) # If you expect equality to occur more often than not, you can save a little # work in the "are equal" case in exchange for costing a little time in the # "not even equal ignoring order case" by only checking length, not keys equality: len(xy) == len(yz) and all(map(eq, xy, yx)) 
+6
Dec 16 '15 at 20:14
source share
— -

I cannot find anything published, but I believe that this logic can justify the behavior:

If you have two dictionaries, d1 and d2, you expect key comparison to check if they have the same keys, right?

 def compare_dict_keys(d1, d2): d1.keys() == d2.keys() 

This function should behave the same for all types of dictionaries (and OrderedDict is a dict type). It would be wrong if such a function started to return False just because d1 and d2 are sorted.

In other words, they should all evaluate the same thing (and they do it):

 >>> {1:2, 3:4}.keys() == {3:4, 1:2}.keys() True >>> {1:2, 3:4}.keys() == OrderedDict([(3,4),(1,2)]).keys() True >>> OrderedDict([(1,2),(3,4)]).keys() == OrderedDict([(3,4),(1,2)]).keys() True 

But OrderedDict is specal, isn't it?

What OrderedDict offers you is a guarantee of the order when you OrderedDict over it. The same guarantee exists for OrderedDict.keys() , but without breaking compatibility with dict .

0
Dec 16 '15 at 20:16
source share



All Articles