为什么 OrderedDict 键视图比较顺序不敏感?

Why does the OrderedDict keys view compare order-insensitive?

为什么 OrderedDict 键视图比较顺序不敏感?

>>> from collections import OrderedDict
>>> xy = OrderedDict([('x', None), ('y', None)])
>>> yx = OrderedDict([('y', None), ('x', None)])
>>> xy == yx
False
>>> xy.keys() == yx.keys()
True

OrderedDict 键视图可以说应该像 OrderedSet 一样工作,但它的行为与 dict.keys 相同(即像通常的 set)。

python2 中的相同 "issue":

>>> xy.viewkeys() == yx.viewkeys()
True

它们是不同的类型,(odict_keysdict_keys的子类)

>>> type(xy.keys())
odict_keys
>>> type({}.keys())
dict_keys

并且已经有一个 order-sensitive keys comparison available that they could have trivially used, but it's apparently only used as a post-check 用于 odict rich 比较。

这是设计决定还是错误?如果这是一个设计决定,我在哪里可以找到对理由的讨论?

看起来 OrderedDict 将各种视图对象的实现委托给公共 dict 实现;即使在 Python 3.5 中也是如此,其中 OrderedDict 获得了 C 加速实现(it delegates object construction to _PyDictView_New and provides no override for the generic view's rich comparison function.

基本上,OrderedDict 视图以与支持 OrderedDict 相同的顺序进行迭代(因为这样做没有成本),但对于 set 类操作,它们执行例如 set、使用内容相等、subset/superset 检查等

这使得忽略排序的选择在某种程度上是有意义的;对于某些 set 操作(例如 &|^),return 值是没有顺序的 set(因为没有OrderedSet,即使有,对于类似 & 的内容,每个视图中的顺序可能不同?),如果某些 [=17],您会得到不一致的行为=]-like 操作是顺序敏感的,有些不是。如果两个 OrderedDict 键视图对顺序敏感,但将 OrderedDict 视图与 dict 视图进行比较则不是。

正如我在评论中指出的那样,您可以很容易地获得对顺序敏感的 keys 比较:

from operator import eq

# Verify that keys are the same length and same set of values first for speed
# The `all` check then verifies that the known identical keys appear in the
# same order.
xy.keys() == yx.keys() and all(map(eq, xy, yx))

# If you expect equality to occur more often than not, you can save a little
# work in the "are equal" case in exchange for costing a little time in the
# "not even equal ignoring order case" by only checking length, not keys equality:
len(xy) == len(yz) and all(map(eq, xy, yx))

我找不到任何已发布的内容,但我想这个逻辑可以证明这种行为是正确的:

如果你有两个字典,d1 和 d2,你会希望通过比较键来检查它们是否具有相同的键,对吗?

def compare_dict_keys(d1, d2):
    d1.keys() == d2.keys()

此函数对于任何类型的字典都应该以相同的方式运行(并且 OrderedDictdict 的一种类型)。如果这样的函数开始返回 False 只是因为 d1 和 d2 已排序,这似乎是错误的。

换句话说,这些都应该评估相同(而且他们确实如此):

>>> {1:2, 3:4}.keys() == {3:4, 1:2}.keys()
True
>>> {1:2, 3:4}.keys() == OrderedDict([(3,4),(1,2)]).keys()
True
>>> OrderedDict([(1,2),(3,4)]).keys() == OrderedDict([(3,4),(1,2)]).keys()
True

但是OrderedDict很特别,不是吗?

OrderedDict 为您提供的是迭代时顺序的保证。 OrderedDict.keys() 存在相同的保证,但不会破坏与 dict.

的兼容性