Inconsistent behaviour between dict.values() and dict.keys() equality in Python 3.x and Python 2.7

The short answer: class dict_values doesn’t have a __eq__ method implemented, but class dict_keys does:

>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True

Therefore, the d.values()‘s == comparison evaluates to False.

The longer answer of why it wasn’t implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):

Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).

Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.

In Python 2.7, d.keys() and d.values() both return a list per the documentation, so you’ll get ordinary list comparison if you try ==. Of course, since the lists aren’t guaranteed to be in any particular order, the comparison doesn’t actually do what you want, but you can perform the comparison if you really want to:

x = {0: 'x', 16: 'x'}
y = {16: 'x', 0: 'x'}

# prints False twice - you'd get True on Python 3.
print x.keys() == y.keys()
print x.items() == y.items()

If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour to Python 3:

# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)