为什么python不包含有序dict(默认情况下)?

为什么python不包含有序dict(默认情况下)?,python,Python,Python有一些很棒的数据建模结构。 以下是一些: +-------------------+-----------------------------------+ | indexed by int | no-indexed by int | +-------------+-------------------+-----------------------------------+ | no-in

Python有一些很棒的数据建模结构。 以下是一些:

              +-------------------+-----------------------------------+
              | indexed by int    | no-indexed by int                 |
+-------------+-------------------+-----------------------------------+
| no-indexed  | [1, 2, 3]         | {1, 2, 3}                         |
| by key      | or                | or                                |
|             | [x+1 in range(3)] | {x+1 in range(3)}                 |
+-------------+-------------------+-----------------------------------+
| indexed     |                   | {'a': 97, 'c': 99, 'b': 98}       |
| by key      |                   | or                                |
|             |                   | {chr(x):x for x in range(97,100)} |
+-------------+-------------------+-----------------------------------+
为什么python在默认情况下不包括按key+int索引的结构(如PHP数组)?我知道有一个库可以模拟这个对象()。但以下是从文档中提取的“OrderedICT”表示:

OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
有一个本机类型在逻辑上应该这样写不是更好吗:

['a': 97, 'b': 98, 'c': 99]
对于有序的信息和通信技术理解,也有同样的逻辑:

[chr(x):x for x in range(97,100)]
在python设计中这样填充表格单元格有意义吗?
有没有什么特别的原因使这项计划尚未实施

Python的字典是作为哈希表实现的。这些数据结构本质上是无序的。虽然可以添加额外的逻辑来跟踪顺序(如Python2.7和3.1+中所做的),但其中涉及的开销非常大

例如,完成许多基本字典操作(例如添加和删除值)需要两倍以上的工作量。这是因为它必须维护一个用于有序迭代的双链接列表,并且它需要一个额外的字典来帮助维护该列表。虽然它的运算仍然是O(1),但常数项更大


由于Python在任何地方都使用
dict
实例(例如,对于所有变量查找),因此它们需要非常快,否则每个程序的每个部分都会受到影响。由于不经常需要有序迭代,因此在一般情况下避免所需的开销是有意义的。如果您需要一个有序字典,请使用标准库中的字典(如果您使用的是早期版本的Python,则使用它建议的方法)。

您的问题似乎是“为什么Python没有带有有序键的本机PHP样式数组?”

Python有三种核心非标量数据类型:list、dict和tuple。Dicts和tuple对于实现语言本身是绝对必要的:它们用于赋值、参数解包、属性查找等。虽然没有真正用于核心语言语义,但列表对于Python中的数据和程序是非常必要的。所有这三个都必须是非常轻量级的,具有非常好的语义理解,并且尽可能快

PHP风格的数组不是这些东西。它们既不快速也不轻量级,运行时复杂度定义不清,而且语义混乱,因为它们可以用于许多不同的事情——请看下面的例子。对于几乎所有用例来说,它们实际上都是糟糕的数据类型,除了创建它们的非常狭窄的用例:表示
x-www-form-encoded
数据。即使在这个用例中,一个失败之处在于早期键覆盖了后期键的值:在PHP中,a=1&a=2会导致数组('a'=>2)。(Python中处理此问题的常见结构是,它具有有序的键和值,每个键可以有多个值。)


PHP有一个数据类型,几乎每个用例都必须使用它,但对任何一个都不是很好。Python有许多不同的数据类型(一些核心数据类型,在外部库中有更多数据类型),这些数据类型在更狭窄的用例中表现出色。

添加了一个新的答案和更新的信息:从CPython3.6开始,
dicts
保留顺序。尽管仍然无法访问索引。很可能是因为基于整数的项查找是不明确的,因为dict键可以是int。(存在一些自定义用例。)

不幸的是,还没有更新以反映这一点,仍然说“键和值以非随机的任意顺序迭代”。讽刺的是,这些文件提到了新的行为:

在版本3.6中更改:接受后,传递给构造函数及其
update()
方法的关键字参数的顺序将保留

这里有一篇文章提到:

一个微小但有用的内部改进:Python3.6保留了更多结构的元素顺序。传递给函数的关键字参数、类中的属性定义以及字典都保留了元素定义时的顺序

因此,如果您只为Py36以后的版本编写代码,则不应该需要
collections.OrderedDict
,除非您正在使用,或基于订单的相等

例如,在Python 2.7中:

>>> d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 0: None}
>>> d
{'a': 1, 0: None, 'c': 3, 'b': 2, 'd': 4}
在Python 3.6中:

>>> d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 0: None}
>>> d
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 0: None}
>>> d['new'] = 'really?'
>>> d[None]= None
>>> d
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 0: None, 'new': 'really?', None: None}
>>> d['a'] = 'aaa'
>>> d
{'a': 'aaa', 'b': 2, 'c': 3, 'd': 4, 0: None, 'new': 'really?', None: None}
>>> 
>>> # equality is not order-based
>>> d1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 0: None}
... d2 = {'b': 2, 'a': 1, 'd': 4, 'c': 3, 0: None}
>>> d2
{'b': 2, 'a': 1, 'd': 4, 'c': 3, 0: None}
>>> d1 == d2
True

从python 3.7开始,这现在是字典的默认行为,它是3.6中的一个实现细节,从2018年6月开始采用:')

dict对象的插入顺序保留性质已被声明为Python语言规范的正式部分


我查看了源代码,它说所有方法的Big-O运行时间都与常规字典相同。。我不知道为什么默认情况下他们不这么做,“列表”不是“有序集”——集合有唯一的元素。“有序集”也不作为本机数据类型存在。
set
list
dict
元组列表
(这样元组的索引-0是唯一的)。但是如果你真的想避免这样做(我怀疑任何一个理智的人都会这样做),那么你应该选择从collections import ordereddict中选择
;myOrderEdict=OrderEdict()
dict可以用int索引——它们可以用任何不可变类型索引。对于Python数据类型来说,这个表不是一个很好的模型。不过,一个简单的有序dict语法会很好。然而,我相信
[key:value,…]
-风格语法(包括ordereddict理解)的语法将是不平凡的。我是最后一个为PHP糟糕的设计决策辩护的人,但声称对于动态语言的核心类型来说,有序哈希映射是“可怕的”选择可以使用“可怕”的例子比“它们的行为不像Python的非核心MultiDict”更可靠。@lafor我实际上给出了一个PHP数组最不可怕的用例示例。“对于这一用例