Python 3.x和Python 2.7中dict.values()和dict.keys()相等性之间的行为不一致

tho*_*747 33 python python-2.7 python-3.x

我发现,比较的结果keys()values()方法的dict内置在自己产生不一致的结果:

instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys()     # Returns True
Run Code Online (Sandbox Code Playgroud)

在Python 2.7中运行上述代码将对两个调用都返回True,这使我相信Python 3的一些实现细节dict_values会导致这种奇怪的行为。

是否有这种行为的原因,或者我偶然发现了一些晦涩的错误?

r.o*_*ook 48

简短的答案:class dict_values没有__eq__实现方法,但是class dict_keys

>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True
Run Code Online (Sandbox Code Playgroud)

因此,d.values()==比较结果为False

关于为什么未实现的更长的答案是一个不同的答案,可以通过对dict-view对象的文档进行更多的挖掘来看出。这部分似乎特别相关(强调我的意思):

键视图是类似集合的,因为它们的条目是唯一且可哈希的。如果所有值都是可哈希的,因此(键,值)对是唯一且可哈希的,则项目视图也将类似于集合。(值的观点不被视为一组样由于项目通常不是唯一的。)对于组样的观点,都为抽象基类中定义的操作的collections.abc.Set可用(例如,==<,或^

由于键必须是唯一的,因此它们具有相似的设置并受的类操作支持是有意义的collections.Set。由于非唯一性,值不像定值。

在Python 2.7然而,d.keys()d.values() 返回list每个文档,因此此限制不适用。由于它们都是同一类型的对象,因此在两个对象上执行相同的操作是有意义的。如果您使用了Python2.7中的dict-view对象,viewkeys并且viewvalues 如其文档中所述,那么您可以预期会有类似的行为:

# 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
Run Code Online (Sandbox Code Playgroud)