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

Andrew Barnert abarnert at yahoo.com
Fri Dec 18 14:58:25 EST 2015


On Dec 18, 2015, at 03:07, Steven D'Aprano <steve at pearwood.info> wrote:
> 
> It's not just equality that behaves strangely with ValuesView. Even when 
> the values are unique and hash-like, they don't behave very "set-like":

But values views are inherently multisets, not sets. Do you really want to say that the multisets {2, 3, 3} and {2, 2, 3} are equal because they have the same elements, even though they have different counts? And is {1, 1, 2} & {1, 1, 3} really just {1} rather than {1, 1}? For some uses of multisets, those rules make sense, but in general, they don't. (Check out how Counter handles the same questions.)

If we had a general notion of multisets in Python, it might make sense to define values views and their behavior in terms of multisets. But defining them in terms of sets because that's sort of close and we have them doesn't make any sense.

If you're thinking we could define what multisets should do, despite not having a standard multiset type or an ABC for them, and apply that to values views, the next question is how to do that in better than quadratic time for non-hashable values. (And you can't assume ordering here, either.) Would having a values view hang for 30 seconds and then come back with the answer you intuitively wanted instead of giving the wrong answer in 20 millis be an improvement? (Either way, you're going to learn the same lesson: don't compare values views. I'd rather learn that in 20 millis.)

> # KeysView and ItemsView are set-like
> py> a.keys() & b.keys()
> {'b', 'a'}
> py> a.items() | b.items()
> {('b', 2), ('a', 1)}
> 
> # values are hashable, but ValuesViews are not set-like
> py> set(a.values()) | set(b.values())
> {1, 2}
> py> a.values() | b.values()
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: unsupported operand type(s) for |: 'ValuesView' and 
> 'ValuesView'
> 
> This is *especially* weird when one realises that ItemsView actually 
> manages to be set-like even when the values are not hashable:
> 
> py> c = odict(x=[])
> py> c.items() & {}
> set()


Try this:

    c = {1: []}
    d = {1: [], 2: []}
    c.items() < d.items()

It can tell that one "virtual set" of key-value pairs is a subset even though they can't actually be represented as sets. The items views take "as set-like as possible" very seriously.



More information about the Python-ideas mailing list