[Python-ideas] Fwd: Why do equality tests between OrderedDict keys/values views behave not as expected?

Franklin? Lee leewangzhong+python at gmail.com
Thu Dec 17 14:50:59 EST 2015


On Thu, Dec 17, 2015 at 11:57 AM, Andrew Barnert <abarnert at yahoo.com> wrote:

> * since all mapping keys and items act like sets (and are Sets), they probably compare like sets

.items() aren't like sets. Or something is very wrong.


>> 1. OrderedDict().values() does not implement __eq__. It uses object
>> equality, which means identity.
>> 1a. dict().values() does not implement __eq__.
>>
>> 2. OrderedDict().keys().__eq__ does not respect order.
>>
>> I'd argue that keys() should be ordered comparisons, and values()
>> could be.
>
> So what happens when you compare the keys, items, or values view from an OrderedDict against the view from another mapping type? Or, for keys and items, against another set type? If you leave that up to the whichever one is on the left, you get cases where a==b and b!=a. If you leave it up to the most derived type (by the usual __rspam__-like rules), that doesn't help anything, since dict_keys_view and odict_keys_view are unrelated except in sharing an abstract base class. And, worst of all, even if you contrive a way for one or the other to always win consistently, you get cases where a==b and b==c and a!=c.

If OrderedDict views raised NotImplemented, I believe the other view
will then have the chance to try its own comparison.


> Under the current rules, I'm pretty sure equality is always symmetric and transitive, ordering is consistent with the normal partial order rules, etc. New rules that seem more intuitive at first glance but break down as soon as you try to think them through don't seem like an improvement.
>
> Finally, why should these comparisons be sequence-like? Yes, OrderedDict and its views do have a defined order, but they still don't act like sequences in other ways. You can't subscript or slice them, they follow dict rather than sequence rules for modifying during iteration (although I believe those rules aren't enforced in the code so you get arbitrary exceptions or wrong values instead of the RuntimeError from dict?), they fail isinstance(x, Sequence), etc. What other non-sequence types implement sequence comparisons?

OrderedDict itself does everything that you might not want its views to do.

OrderedDict implements order-sensitive comparison. It breaks all the
rules you can think of that order-sensitive comparisons can break.
Transitivity is already a problem. "Who's comparing?" is already a
problem, and it's made its choice ("Equality tests between OrderedDict
objects and other Mapping objects are order-insensitive like regular
dictionaries."). The question now is, should views be made consistent
with the OrderedDict itself?

There are three options:
1. Deprecate the OrderedDict ordered comparison, to make it consistent
with the views.
2. Make the views consistent with the OrderedDict.
3. Do nothing.


>> As a plus, this could be more efficient than unordered
>> comparisons, since it's just
>>    return all(x == y for x, y in zip(self.keys(), other.keys()))
>> instead of packing each into a set and comparing the sets.
>
> I think you want zip_longest(self.keys(), other.keys(), fill=object()) or equivalent; otherwise {1, 2} will be equal to {1, 2, 3} .

I actually want
    return len(self.keys()) == len(other.keys()) and all(x == y for x,
y in zip(self.keys(), other.keys()))

This should be more efficient than set comparisons. It's a bonus, not a reason.


More information about the Python-ideas mailing list