为什么** kwargs映射比较与OrderedDict有所不同?

根据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自3.5开始实现了一个C实现的有序词典,所以它可以被直接使用(或者,如果性能仍然是一个问题,那么使用3.6紧凑词典的一个瘦子类可以实现更快的实现)。

为什么函数收到的有序映射不能在相等比较中进行排序?


你的第一个'为什么'的答案是因为这个特性是通过在CPython中使用纯dict来实现的。 正如Ryan的回答指出的那样,这意味着比较不会对顺序敏感。

第二个'为什么'这是为什么这不使用OrderedDict

使用OrderedDict是PEP 486初稿中规定的最初计划。该答复中重复的想法是收集一些perf数据以显示插入OrderedDict的效果,因为这是一个争论点,想法在之前浮现了。 PEP的作者甚至提到在该主题的最终答复中,保留命令是另一种选择。

之后,关于这个话题的谈话似乎已经停止了,直到Python 3.6出现。 当新字典出现时,它具有刚刚实现PEP 486的良好副作用(如此Python-dev线程所述)。 该线程中的特定消息还说明了作者如何将OrderedDict这一术语改为有序映射。 (这也是当PEP 468在最初的一次之后作出新的承诺时)

据我所知,这个改写是为了让其他实现能够在他们认为合适时提供这个功能。 CPython和PyPy已经有了一个轻松实现PEP 468的词典,其他实现可以选择OrderedDict ,其他实现可以用于另一种有序映射形式。

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

虽然它看起来像一个问题,但它确实不是。 正如@ user2357112指出的那样, ==没有保证。 PEP 468只保证订单。 据我所知, ==基本上是实现定义的。


总之,它比较CPython中的平等,因为CPython中的kwargs是一个dict ,它是一个dict因为在3.6之后,整个事情才起作用。


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

OrderedDict对象之间的相等测试是顺序敏感的,并且以list(od1.items())==list(od2.items())OrderedDict对象与其他Mapping对象之间的相等测试与常规字典一样对顺序不敏感。 这允许OrderedDict对象在使用常规字典的任何地方被替换。


“有序映射”仅意味着映射必须保持顺序。 这并不意味着该顺序必须是映射==关系的一部分。

PEP 468的目的只是为了保存订购信息。 将订单作为==一部分会产生后向不兼容性,对任何激发PEP 468的用例都没有任何实际益处。使用OrderedDict也会更加昂贵(因为OrderedDict仍然维护其自己的单独链接列表以跟踪订单,并且它可以放弃这个链表并不会牺牲popitemmove_to_end大O效率)。

链接地址: http://www.djcxy.com/p/30355.html

上一篇: Why does the **kwargs mapping compare equal with a differently ordered OrderedDict?

下一篇: MySQL Server has gone away when importing large sql file