本文介绍了Python 3.x 和 Python 2.7 中 dict.values() 和 dict.keys() 相等之间的不一致行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现将 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().__eq__(d.values())未实现>>>d.keys().__eq__(d.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()

如果您使用了 viewkeysviewvalues 如 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() 相等之间的不一致行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 19:54
查看更多