Python dict 的视图对象的等价性 [duplicate]

Equivalence of view objects of Python dict [duplicate]

提问人:tungli 提问时间:4/15/2021 更新时间:4/15/2021 访问量:647

问:

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

事实上,在相同的 s(甚至不是副本)的情况下,它也是:dictFalse

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

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

Python 字典 相等

答:

0赞 Stephen 4/15/2021 #1

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

如果您尝试检查 和 是否是同一个实例,则可以使用 .abis

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

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

一个 dict.values() 视图和另一个视图之间的相等性比较将 始终返回 False。当将 dict.values() 与 本身:

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

评论

0赞 Barmar 4/15/2021
这并不能解释为什么和对象相等,但对象不相等keys()items()values()
0赞 tungli 4/15/2021
正如@Barmar所说,它没有抓住重点。我可以理解,例如 回来了,但随之而来的是奇怪的。a.values() is a.values()False==
0赞 tungli 4/15/2021
此外,现在是插入顺序的(从 3.7 开始)dict
0赞 Stephen 4/15/2021
我更新了答案来回答这个问题。
0赞 user2357112 4/15/2021
该文档部分不太正确 - on views 可以返回 ,但前提是您将相同的视图对象与自身进行比较。调用两次会返回两个不同的视图对象,因此您可以得到 .==valuesTruevaluesFalsed.values() == d.values()
2赞 Barmar 4/15/2021 #2

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

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

对于 和 ,字典视图的文档说:dict.keys()dict.items()

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

评论

0赞 tungli 4/15/2021
谢谢!我错过了。关于为什么它必须返回 False 的任何见解?这似乎是浪费一个好的操作员......
1赞 Barmar 4/15/2021
为了避免做一些昂贵的事情,比如对所有值的列表进行排序,以便比较它们。
0赞 Barmar 4/15/2021
keys并且可以像集合一样处理,因为密钥保证是唯一的和可哈希的。但值可以有重复项。items
3赞 user2357112 4/15/2021 #3

keys视图是类似集合的(或者对于具有不可哈希值的视图来说,大部分是类似集合的)——它们在许多方面都表现得像对象,特别是,对此类视图执行测试很容易。这样,这些视图就可以根据两个视图是否包含相同的元素来支持高效操作。itemsitemssetin==

对于视图,没有很好的方法来实现这样的操作,因此视图不会实现任何花哨的东西。它们只是继承了 的默认实现,因此只有当两个视图是同一个对象时,它们才会被视为相等。即使对于同一字典的两个视图,也只有在它们实际上是相同的视图对象时才会得到:values==values==__eq__objectvaluesTrue

In [2]: x = {}

In [3]: x.values() == x.values()
Out[3]: False

In [4]: v = x.values()

In [5]: v == v
Out[5]: True

评论

0赞 tungli 4/15/2021
谢谢你的回答!“没有好的方法可以实现这样的==操作......” -> 有什么问题:?def __eq__(self, other): return all(i == j for i, j in zip(self, other))
2赞 Barmar 4/15/2021
@tungli 这要求两个词典的元素顺序相同。
1赞 user2357112 4/15/2021
@tungli:这会将元素顺序带入比较中,从而导致相等的字典具有不相等的值视图。它与字典比较以及所有其他视图比较的工作方式不一致。(另外,您忘了先检查。len
0赞 user2357112 4/15/2021
此外,这些设计决策是在指令成为顺序保留之前做出的。
0赞 Barmar 4/15/2021
不确定这是否重要,因为这些运营商都不关心秩序。也许实现价值观平等的最佳方式是Collections.counter(self) == Collections.counter(other)