Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

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

I have found that comparing the results of the keys() and values() methods of the dict built-in to themselves results in inconsistent results:

instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys()     # Returns True

Running the above code in Python 2.7 will return True for both calls, leading me to believe that there is some implementation detail in Python 3's dict_values that causes this strange behaviour.

Is there a reason for this behaviour or have i stumbled upon some obscure bug?

question from:https://stackoverflow.com/questions/55026840/inconsistent-behaviour-between-dict-values-and-dict-keys-equality-in-python

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:

# 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...