wim*_*wim 12 python function ordereddictionary kwargs python-3.6
根据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
Run Code Online (Sandbox Code Playgroud)
虽然现在保留了迭代顺序,但kwargs似乎表现得像比较的普通字典.从3.5开始,Python有一个C实现的有序字典,因此它可以直接使用(或者,如果性能仍然是一个问题,使用3.6紧凑字典的瘦子类更快的实现).
为什么函数接收的有序映射不会在相等比较中遵循排序?
Ry-*_*Ry- 13
无论什么样的"有序映射"的意思,只要它不一定OrderedDict,OrderedDict的==不会考虑到它的顺序.文档:
OrderedDict对象之间的等式测试是对顺序敏感的,并且实现为list(od1.items())==list(od2.items()).对象和其他对象之间的等式测试对常规字典顺序不敏感.OrderedDictMapping这允许OrderedDict在使用常规字典的任何地方替换对象.
"有序映射"仅表示映射必须保留顺序.这并不意味着订单必须是映射==关系的一部分.
PEP 468的目的只是为了保存订购信息.订单成为其中一部分==会产生向后不兼容性而对任何激发PEP 468的用例没有任何实际好处.使用OrderedDict也会更加昂贵(因为OrderedDict仍然保持自己单独的链接列表来跟踪订单,并且它不能放弃链表没有牺牲大O效率popitem和move_to_end).
你的第一个'为什么'的答案是因为这个功能是通过dict在CPython中使用plain来实现的.正如@ Ryan的答案指出的那样,这意味着比较不会对订单敏感.
第二个'为什么'这就是为什么这不使用OrderedDict.
使用a OrderedDict是PEP 486 第一稿中所述的初始计划.如本回复中所述,这个想法是收集一些性能数据以显示插入的影响,OrderedDict因为这是一个争论点,当时的想法是之前飘来飘去.PEP的作者甚至提到保留dict的命令是该主题的最终答复中的另一个选项.
在那之后,关于该主题的对话似乎已经消失,直到Python 3.6出现.当新的dict出现时,它具有开箱即用的PEP 486的良好副作用(正如这个Python-dev线程所述).该线程中的特定消息还说明了作者如何将术语OrderedDict更改为"有序映射".(这也是在最初的PEP 468之后的PEP 468的新提交时)
据我所知,这个重写是为了允许其他实现提供他们认为合适的功能.CPython和PyPy已经有了一个很容易实现PEP 468的dict,其他实现可能会选择一个OrderedDict,其他实现可能会采用另一种形式的有序映射.
但这确实为问题打开了大门.理论上,它确实意味着,在Python 3.6的实现中,OrderedDict作为实现此功能的结构,比较将是对顺序敏感的,而在其他(CPython)中它不会.(在Python 3.7中,所有dicts都需要按插入顺序排列,所以这一点可能没有实际意义,因为所有实现都会使用它**kwargs)
虽然看起来确实是一个问题,但事实并非如此.正如@ user2357112指出的那样,无法保证==.PEP 468 仅保证订单.据我所知,==基本上是实现定义的.
简而言之,它在CPython中比较相等,因为kwargs在CPython中dict它是a 而且它是dict因为在3.6整个事情刚刚起作用之后.
| 归档时间: |
|
| 查看次数: |
992 次 |
| 最近记录: |