OrderedDict和dict的键顺序相同吗?

  • 本文关键字:顺序 dict OrderedDict python
  • 更新时间 :
  • 英文 :


dict自Python 3.6以来保持插入顺序(参见此)。

OrderedDict就是为此目的而开发的(Python 3.6之前)。

从Python 3.6开始,dictOrderedDict的键顺序是否总是相同的?

我想知道我是否可以在我的代码中做到这一点,并始终具有相同的行为(除了相等,以及OrderedDict中的一些扩展方法),但更有效:

if sys.version_info[:2] >= (3, 6):
OrderedDict = dict
else:
from collections import OrderedDict 

或者换句话说,对于Python>=3.6,是否有理由使用OrderedDict?

对于迭代,OrderedDictdict都是插入顺序¹。如果迭代顺序是唯一的决定点,特别是在不需要重新排序的情况下,实际上没有理由使用OrderedDict
显然,如果需要比较顺序,OrderedDictdict是不可互换的。

或者换句话说,对于Python>=3.6,是否有理由使用OrderedDict?

这些天OrderedDictdict就像dequelist,基本上。OrderedDict/deque基于链表²,而dict/list基于数组。前者有更好的pop/move/FIFO语义,因为项目可以从开始/中间删除而不移动其他项目。

由于数组通常非常适合缓存,因此链表的优势只适用于非常大的容器。此外,OrderedDict(与deque不同)不保证其链表语义,因此它的优势可能不具有可移植性。如果需要许多pop/move/FIFO操作,则应该主要使用OrderedDict,并且基准测试可以比较dictOrderedDict在实践中的性能。


¹这适用于所有当前支持的符合Python语言规范的实现,即自Python 3.6以来的CPython和PyPy。

²OrderedDict在CPython中仍然保留O(1)键访问。这是通过有一个"regular"查找表,使用链表对项之间的顺序和查找表对直接项访问。很复杂。

我意识到相等的不同行为(__eq__)实际上可能是一个主要问题,为什么这样的代码片段可能不好。

然而,你可能仍然可以这样做:

if sys.version_info[:2] >= (3, 6):
OrderedDict = dict
else:
from collections import OrderedDict as _OrderedDict
class OrderedDict(_OrderedDict):
__eq__ = dict.__eq__
__ne__ = dict.__ne__

不同的是,与原来的collections.OrderedDict相比,{1:1,2:2}{2:2,1:1}不一样,但对于dict和我在这个例子中覆盖的OrderedDict,它是一样的。

一些行为保持不变,但OrderedDict是可逆的,dict不是:

from collections import OrderedDict
d = { "a" : 1, "c" : 2}
od = OrderedDict(d.items())
print(list(reversed(od)))
print(list(reversed(d)))

['c', 'a']
Traceback (most recent call last):
File "path/to/file", line 8, in <module>
print(list(reversed(d)))
TypeError: 'dict' object is not reversible

来自文档:

除了常用的映射方法,有序字典也使用reversed()支持反向迭代。

相关内容

  • 没有找到相关文章

最新更新