Dominik Vilsmeier writes:
Well, the point is that this "except comparisons" is not quite true:
>>> i = {'a': []}.items() >>> s = {('a', 1)} >>> i == s TypeError: unhashable type: 'list'
If passed a set as `other` operand, dict_items seems to decide to convert itself to a set, for no obvious reasons since, as you mentioned, it does know how to compare itself to another view containing non-hashable values:
The obvious reason is that they didn't want to implement the comparison if you didn't have to, the dict.items() view is a Set, so the obvious implementation is s == set(i).
So if you're dealing with items views and want to compare them to a set representing dict items, then you need an extra `try/except` in order to handle non-hashable values in the items view.
Sounds like you have a change to propose here, then. Put the try/except in the __eq__ for the items view class when comparing against a set. I would expect it to be accepted, as comparing items views is pretty expensive so the slight additional overhead would likely be acceptable, and if you get the exception, you know the equality comparison against a set is false since a set cannot contain that element, so this possibility can't affect worst-case performance by much, if at all.
Surely [dict.values equality comparison having object equality semantics] must be a relic from pre-3.7 days where dicts were unordered and hence order-based comparison wouldn't be possible (though PEP 3106 describes an O(n*m) algorithm). However the current behavior is unfortunate because it might trick users
You mean "users might trick themselves". We provide documentation for exactly this reason.
So why not make dict_values a Sequence, providing __getitem__ and additionally order-based __eq__ comparison?
Besides making dict more complex, and possibly preventing future improvements because of backward compatibility with this requirement, dict comparisons and dict.keys comparisons are done with set semantics. So I would expect dict.values comparisons to have multiset semantics, not sequence semantics. I would feel very cheated when I found out d1.values() == d2.values() had sequence equality semantics! If you want sequence semantics for dict.values equality, I'm pretty sure this DTRT: def sequence_equal(v1, v2): # v1, v2 are dict.values objects return len(v1) == len(v2) and all(x == y for x, y in zip(v1, v2)) But I can't imagine wanting that. The only time I ever care that dicts are ordered is writing doctests, and then I'm very happy! But I can't recall ever wanting to write a doctest for equality on dict.values. Equality of the dict itself is always what I want.