【问题标题】:Inconsistent behaviour between dict.values() and dict.keys() equality in Python 3.x and Python 2.7Python 3.x 和 Python 2.7 中 dict.values() 和 dict.keys() 相等之间的行为不一致
【发布时间】:2019-07-28 08:08:12
【问题描述】:

我发现将内置的dictkeys()values() 方法的结果与自身进行比较会导致结果不一致:

instance = {'one': 1}

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

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

这种行为是有原因的还是我偶然发现了一些不为人知的错误?

【问题讨论】:

  • 这似乎很有趣,因为我刚刚检查了 id 的两个值,它们也相同,== 仍然返回 False。我认为必须深入挖掘源代码才能找到原因。
  • 不知道答案,不过可以简化为d.values() == d.values()是假的。
  • 很好,我将编辑我的问题,使其更笼统。

标签: python python-3.x python-2.7


【解决方案1】:

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

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

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

为什么它没有被实现的更长的答案是一个不同的答案,可以在the documentation of dict-view objects 上进行更多的挖掘。这部分似乎特别相关(强调我的):

键视图类似于集合,因为它们的条目是唯一且可散列的。 如果所有值都是可散列的,那么 (key, value) 对是唯一的并且 可散列的,那么项目视图也是类似集合的。 (价值观观点不 被视为类似集合,因为条目通常不是唯一的。)对于 类似集合的视图,为抽象基础定义的所有操作 collections.abc.Set 类可用(例如,==<^

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

在 Python 2.7 中,d.keys()d.values() 两者都返回 list per the documentation,因此如果您尝试 ==,您将获得普通的列表比较。当然,由于不能保证列表按任何特定顺序排列,因此比较实际上并不能满足您的要求,但如果您真的想要,您可以执行比较:

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()

如果您使用了 viewkeysviewvalues as mentioned in the documentation of dict-view objects in Python2.7,那么您可以期待与 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 2 上,具有相同键的两个不同 dict 对象可能会以不同的顺序返回它们,而文档暗示在 Python 3 上,键的顺序在比较期间会被忽略。
猜你喜欢
  • 2014-08-31
  • 1970-01-01
  • 2019-06-13
  • 2013-08-06
  • 1970-01-01
  • 2016-04-13
  • 2018-04-20
  • 2017-05-25
相关资源
最近更新 更多