有没有理由不使用OrderedDict?

tem*_*ame 62 python dictionary ordereddictionary python-3.x

我指的是模块中的OrderedDictcollections,它是一个有序字典.

如果它具有可订购的附加功能,我意识到这可能通常不是必要的,但即便如此,是否有任何缺点?它慢了吗?它缺少任何功能吗?我没有看到任何遗漏的方法.

简而言之,为什么我不应该总是使用它而不是普通的字典呢?

Tim*_*ers 131

OrderedDict是一个子类dict,需要更多的内存来跟踪添加键的顺序.这不是微不足道的.该实现增加了第二个dict封面,以及所有键的双重链接列表(这是记住订单的部分),以及一堆弱反射代理.它并没有慢很多,但至少使用普通的内存加倍dict.

但如果合适,请使用它!这就是为什么它在那里:-)

这个怎么运作

基本字典只是一个普通的字典映射键值 - 它根本不是"有序"的.当<key, value>加入对,则key附加到列表.列表是记住订单的部分.

但如果这是一个Python列表,删除一个密钥需要O(n)两倍的时间: O(n)在列表中找到密钥的O(n)时间,以及从列表中删除密钥的时间.

所以这是一个双向链表.这使得删除键常量(O(1))时间.但是我们仍然需要找到属于密钥的双向链表节点.为了使操作O(1)时间也是如此,第二个 - 隐藏 - 字典将键映射到双向链表中的节点.

因此,添加新<key, value>对需要将该对添加到基本dict,创建一个新的双向链表节点来保存密钥,将新节点附加到双向链表,并将密钥映射到隐藏字典中的新节点.工作量增加了一倍多,但O(1)总体上还是(预期的情况)时间.

类似地,删除当前存在的密钥也是工作量的两倍多,但O(1)总体预期时间:使用隐藏的字典找到密钥的双向链表节点,从列表中删除该节点,并从两个字节中删除密钥.

等等.效率很高.

  • 等等......你是谁的WROTE TIMSORT!从蟒蛇天堂意外下降回答我的低调问题.谢谢! (66认同)
  • @GrijeshChauhan,我读了源代码 - 我是一个核心Python开发人员,这就是我回答大多数问题的方法**我有 - LOL ;-)你可以在`Lib/collections/__ init __.py找到代码在你的Python源代码树中. (25认同)
  • 大声笑!你非常欢迎,@ Aerovistae - 这是一个值得的问题;-) (10认同)
  • 我发现当我告诉人们"你可以在你的Python源代码树中找到代码"时,他们永远不会看,但是当我[链接到hg repo]时(http://hg.python.org/cpython/file/3.3/Lib /collections/__init__.py#!19)他们有时会这样做.(通常只有在阅读消息来源时才会引起他们的疑问.) (10认同)
  • @GrijeshChauhan转到你的python解释器,输入`import this`然后按回车键,编写它的人就是回答这个问题的人. (4认同)
  • 很好的答案,但我们需要一个链接来进一步阅读,从哪里重新阅读这些信息. (3认同)

Dim*_*nek 7

多线程

如果您的字典是从没有锁定的多个线程访问的,尤其是作为同步点.

vanilla dict操作是原子的,而在Python中扩展的任何类型都不是.

事实上,我甚至不确定OrderedDict是线程安全的(没有锁定),虽然我不能忽视它是非常仔细编码并满足重入的定义的可能性.

较小的恶魔

如果您创建大量这些词典,则使用内存

cpu用法,如果您的所有代码都是这些词典


Fli*_*imm 7

从 Python 3.7 开始,所有字典都保证有序。Python 贡献者确定切换到使dict排序不会对性能产生负面影响。我不知道与Python >= 3.7OrderedDict相比的性能如何dict,但我想它们是可比的,因为它们都是有序的。

请注意,OrderedDict和的行为之间仍然存在差异dict。另请参阅:OrderedDict 在 Python 3.7 中会变得多余吗?