为什么** kwargs映射与不同排序的OrderedDict相等?

问题描述 投票:11回答:4

PEP 468说:

从版本3.6开始,Python将保留传递给函数的关键字参数的顺序。为了实现这一点,收集的kwargs现在将是有序映射。请注意,这并不一定意味着OrderedDict

在这种情况下,为什么这个有序映射无法尊重与Python的规范有序映射类型collections.OrderedDict的等式比较:

>>> from collections import OrderedDict
>>> data = OrderedDict(zip('xy', 'xy'))
>>> def foo(**kwargs):
...     return kwargs == data
... 
>>> foo(x='x', y='y')  # expected result: True
True
>>> foo(y='y', x='x')  # expected result: False
True

虽然现在保留了迭代顺序,但kwargs似乎表现得像比较的普通字典。 Python有一个C实现的有序字典since 3.5,所以可以想象它可以直接使用(或者,如果性能仍然是一个问题,使用3.6紧凑字典的瘦子类更快的实现)。

为什么函数接收的有序映射不会在相等比较中遵循排序?

python function python-3.6 ordereddictionary kwargs
4个回答
6
投票

你的第一个“为什么”的答案是因为这个功能是通过在CPython中使用普通的dict来实现的。正如@ Ryan的答案指出的那样,这意味着比较不会对订单敏感。

第二个“为什么”这就是为什么这不使用OrderedDict

使用OrderedDict是PEP 486的first draft中所述的初始计划。如in this reply所述,该想法是收集一些性能数据以显示堵塞OrderedDict的影响,因为当这个想法浮出水面时这是一个争论的焦点。在此之前。 PEP的作者甚至暗示保留dict的顺序是该线程中final reply的另一种选择。

在那之后,关于该主题的对话似乎已经消失,直到Python 3.6出现。当新的词典出现时,它具有开箱即用的PEP 486(如this Python-dev thread states)的良好副作用。该线程中的特定消息还说明了作者如何将术语OrderedDict更改为Ordered Mapping。 (这也是在最初的一个之后的new commit on PEP 468被制作出来的时候)

据我所知,这个重写是为了允许其他实现提供他们认为合适的功能。 CPython和PyPy已经有了一个很容易实现PEP 468的字典,其他实现可能会选择OrderedDict,其他实现可能会采用另一种形式的有序映射。

但这确实为问题打开了大门。理论上,它确实意味着在Python 3.6的实现中使用OrderedDict作为实现此功能的结构,比较将是顺序敏感的,而在其他(CPython)它不会。 (在Python 3.7中,所有qazxswpo都需要按插入顺序排列,因此这一点可能没有实际意义,因为所有实现都会将它用于dict

虽然看起来确实是一个问题,但事实并非如此。正如@ user2357112指出的那样,**kwargs无法保证。 PEP 468仅保证订单。据我所知,==基本上是实现定义的。


简而言之,它在CPython中比较相同,因为CPython中的==kwargs而且它是dict,因为在dict之后整个事情才奏效。


14
投票

无论“有序映射”是什么意思,只要它不一定是3.6OrderedDictOrderedDict就不会考虑它的顺序。 ==

Docs:对象之间的等式测试是对顺序敏感的,并且实现为OrderedDictlist(od1.items())==list(od2.items())对象和其他OrderedDict对象之间的等式测试对常规字典顺序不敏感。这允许在使用常规字典的任何地方替换Mapping对象。


9
投票

“有序映射”仅表示映射必须保留顺序。这并不意味着顺序必须是映射的OrderedDict关系的一部分。

PEP 468的目的只是为了保存订购信息。订单成为==的一部分将产生向后不兼容性,而没有任何实际利益促成PEP 468的任何用例。使用==也会更昂贵(因为OrderedDict仍然保持自己单独的链接列表来跟踪订单,它可以'在不牺牲OrderedDictpopitem的大O效率的情况下放弃该链表。


1
投票

只是要补充一下,如果你确实想要进行这项检查(不依赖于实现细节(即便如此,也不会在python 3.7中)),只需要做

move_to_end

因为这保证是真的。

© www.soinside.com 2019 - 2024. All rights reserved.