问题描述
我发现将 dict
内置的 keys()
和 values()
方法的结果与它们自己的结果进行比较结果不一致:
instance = {'one': 1}instance.values() == instance.values() # 返回假instance.keys() == instance.keys() # 返回真
在 Python 2.7 中运行上述代码将在两次调用中都返回 True,这让我相信 Python 3 的 dict_values
中有一些实现细节导致了这种奇怪的行为.
这种行为是有原因的还是我偶然发现了一些不起眼的错误?
简短的回答:class dict_values
没有实现 __eq__
方法,但是 class dict_keys
做了:
因此,d.values()
的 ==
比较结果为 False
.
关于为什么没有实施的更长答案是另一个不同的答案,可以通过在 dict-view 对象的文档.这部分似乎特别相关(重点是我的):
键视图类似于设置,因为它们的条目是唯一且可散列的.如果所有值都是可散列的,那么 (key, value) 对是唯一的并且可散列,那么项目视图也是类似设置的.(价值观观点不是由于条目通常不是唯一的,因此被视为类似集合.)对于类似集合的视图,为抽象基础定义的所有操作类 collections.abc.Set
可用 (例如,==
、<
或 ^
>).
由于键必须是唯一的,因此它们类似于 set 并且由 collections.Set
的类操作支持是有意义的.由于非唯一性,值不是类似设置的.
在 Python 2.7 中,d.keys()
和 d.values()
两者 返回一个 list
每个文档,所以你会得到普通的列表比较如果您尝试 ==
.当然,由于不能保证列表按任何特定顺序排列,因此比较实际上并没有按照您的意愿进行,但是如果您真的想要,您可以执行比较:
x = {0: 'x', 16: 'x'}y = {16: 'x', 0: 'x'}# 打印两次 False - 你会在 Python 3 上得到 True.打印 x.keys() == y.keys()打印 x.items() == y.items()
如果您使用了 viewkeys
和 viewvalues
如 Python2.7 中的 dict-view 对象文档中所述,那么您可以期待与 Python 3 类似的行为:
# Python 2.7从集合导入集# 在 Python 3.x 中,这将来自 collections.abc import Setd = {一个":1}打印 isinstance(d.viewkeys(), Set)# 真的打印 isinstance(d.viewvalues(), Set)# 错误的打印 d.viewkeys() == d.viewkeys()# 真的打印 d.viewvalues() == d.viewvalues()# 错误的
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?
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):
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
这篇关于Python 3.x 和 Python 2.7 中 dict.values() 和 dict.keys() 相等之间的不一致行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!