Python dict 的视图对象的等价性

问题描述

Python dict 的视图对象的比较与我预期的不同:

a = {0 : 'a',1 : 'b'}
b = {1 : 'b',0 : 'a'}

print(a == b) # True
print(a.keys() == b.keys()) # True
print(a.values() == b.values()) # False
print(a.items() == b.items()) # True

对于dict.values()False 有什么特殊原因吗?

其实在同一个dict的情况下(甚至不是副本),也是False

a = {0 : 'a',1 : 'b'}
print(a.values() == a.values()) # False

这个视图对象的相等性意味着什么?

解决方法

字典视图类实现它们自己的相等方法。 dict.values() 的文档特别指出:

一个 dict.values() 视图和另一个视图之间的相等比较将始终返回 False。这也适用于将 dict.values() 与其自身进行比较

对于 dict.keys()dict.items()dictionary views 的文档说:

键视图是类似设置的,因为它们的条目是唯一且可散列的。如果所有值都是可散列的,因此 (key,value) 对是唯一且可散列的,则项目视图也是类似集合的。 (值视图不被视为类集合,因为条目通常不是唯一的。)对于类集合视图,为抽象基类 collections.abc.Set 定义的所有操作都可用(例如,{{1} }、==<)。

,

keysitems 视图是类似集合的(或者对于具有不可散列值的 items 视图大多类似集合)——它们在许多情况下的行为类似于 set 对象方式,特别是,对此类视图执行 in 测试很容易。这让这些视图支持基于两个视图是否包含相同元素的高效 == 操作。

对于 values 视图,没有实现此类 == 操作的好方法,因此 values 视图不要为 {{1 }}。它们只是从 == 继承默认的 __eq__ 实现,因此两个 object 视图只有在它们是同一个对象时才会被认为是相等的。即使对于同一个 dict 的两个视图,如果它们实际上是同一个视图对象,您也只会得到 values

True
,

dict 是无序的,这意味着只要 a 中的所有键都存在于 b 中并且 b 中的所有键都存在于 a 和这些键的所有值都相等,两个集合相等。

如果您尝试检查 ab 是否是相同的实例,那么您可以使用 is

>>> a = {0 : 'a',1 : 'b'}
>>> b = {1 : 'b',0 : 'a'}

>>> a is b
False

>>> a = {0 : 'a',1 : 'b'}
>>> b = a

>>> a is b
True

至于a.values() == b.values()为什么返回False的问题,这是Python语言做出的选择。引用自 Python 文档:

一个 dict.values() 视图和另一个视图之间的相等比较将 总是返回 False。这也适用于将 dict.values() 与 本身:

>>> d = {'a': 1}
>>> d.values() == d.values()
False