简体   繁体   English

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

[英]Why python does not include a ordered dict (by default)?

Python have some great structures to model data. Python有一些很好的结构来建模数据。 Here are some : 这里有一些 :

              +-------------------+-----------------------------------+
              | 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)} |
+-------------+-------------------+-----------------------------------+

Why python does not include by default a structure indexed by key+int (like a PHP Array) ? 为什么python默认不包含由key + int索引的结构(如PHP数组)? I know there is a library that emulate this object ( http://docs.python.org/3/library/collections.html#ordereddict-objects ). 我知道有一个模拟这个对象的库( http://docs.python.org/3/library/collections.html#ordereddict-objects )。 But here is the representation of a "orderedDict" taken from the documentation : 但这里是从文档中获取的“orderedDict”的表示:

OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

Wouldn't it be better to have a native type that should logically be writen like this: 拥有一个逻辑上应该写的本机类型不是更好吗:

['a': 97, 'b': 98, 'c': 99]

And same logic for orderedDict comprehension : 与orderedDict理解相同的逻辑:

[chr(x):x for x in range(97,100)]

Does it make sense to fill the table cell like this in the python design? 在python设计中填充像这样的表格单元格是否有意义? It is there any particular reason for this to not be implemented yet? 这有什么特别的原因尚未实施吗?

Python's dictionaries are implemented as hash tables. Python的字典被实现为哈希表。 Those are inherently unordered data structures. 这些本质上是无序的数据结构。 While it is possible to add extra logic to keep track of the order (as is done in collections.OrderedDict in Python 2.7 and 3.1+), there's a non-trivial overhead involved. 虽然可以添加额外的逻辑来跟踪顺序(如在Python 2.7和3.1+中的collections.OrderedDict中所做的那样),但是涉及到一个非平凡的开销。

For instance, the recipe that the collections documentation suggest for use in Python 2.4-2.6 requires more than twice as much work to complete many basic dictionary operations (such as adding and removing values). 例如, collections文档建议在Python 2.4-2.6中使用的配方需要两倍多的工作来完成许多基本字典操作(例如添加和删除值)。 This is because it must maintain a doubly-linked list to use for ordered iteration, and it needs an extra dictionary to help maintain the list. 这是因为它必须维护一个双向链表以用于有序迭代,并且它需要一个额外的字典来帮助维护列表。 While its operations are still O(1), the constant terms are larger. 虽然其操作仍为O(1),但常数项更大。

Since Python uses dict instances everywhere (for all variable lookups, for instance), they need to be very fast or every part of every program will suffer. 由于Python在任何地方使用dict实例(例如,对于所有变量查找),因此它们需要非常快或者每个程序的每个部分都会受到影响。 Since ordered iteration is not needed very often, it makes sense to avoid the overhead it requires in the general case. 由于不经常需要有序迭代,因此在一般情况下避免它所需的开销是有意义的。 If you need an ordered dictionary, use the one in the standard library (or the recipe it suggests, if you're using an earlier version of Python). 如果您需要有序字典,请使用标准库中的字典(或者它建议的配方,如果您使用的是早期版本的Python)。

Your question appears to be "why does Python not have native PHP-style arrays with ordered keys?" 您的问题似乎是“为什么Python没有带有序键的本机PHP样式数组?”

Python has three core non-scalar datatypes: list, dict, and tuple. Python有三种核心非标量数据类型:list,dict和tuple。 Dicts and tuples are absolutely essential for implementing the language itself: they are used for assignment, argument unpacking, attribute lookup, etc. Although not really used for the core language semantics, lists are pretty essential for data and programs in Python. Dicts和元组对于实现语言本身是绝对必要的:它们用于赋值,参数解包,属性查找等。虽然没有真正用于核心语言语义,但列表对于Python中的数据和程序非常重要。 All three must be extremely lightweight, have very well-understood semantics, and be as fast as possible. 这三个必须非常轻量级,具有非常好理解的语义,并且尽可能快。

PHP-style arrays are none of these things. PHP风格的数组都不是这些。 They are not fast or lightweight, have poorly defined runtime complexity, and they have confused semantics since they can be used for so many different things--look at the array functions . 它们不是快速或轻量级的,运行时复杂性很差,并且它们混淆了语义,因为它们可以用于许多不同的东西 - 查看数组函数 They are actually a terrible datatype for almost every use case except the very narrow one for which they were created: representing x-www-form-encoded data. 它们实际上是几乎每个用例的可怕数据类型,除了它们被创建的非常窄的用例:表示x-www-form-encoded数据。 Even for this use case a failing is that earlier keys overwrite the value of later keys: in PHP ?a=1&a=2 results in array('a'=>2) . 即使对于这个用例,失败的是早期的密钥会覆盖以后密钥的值:在PHP中?a=1&a=2导致array('a'=>2) (A common structure for dealing with this in Python is the MultiDict , which has ordered keys and values, and each key can have multiple values.) (在Python中处理此问题的常见结构是MultiDict ,它具有有序键值,每个键可以有多个值。)

PHP has one datatype that must be used for pretty much every use case without being great for any of them. PHP有一种数据类型,几乎每个用例都必须使用它,而不适用于任何用例。 Python has many different datatypes (some core, many more in external libraries) which excel at much more narrow use cases. Python有许多不同的数据类型(一些核心,在外部库中更多),它们在更窄的用例中表现出色。

Adding a new answer with updated information: As of C Python3.6, dicts preserve order . 添加与更新信息的新的答案:以C Python3.6的, dicts维持秩序 Though still not index-accessible. 虽然仍然无法索引。 Most likely because integer-based item-lookup is ambiguous since dict keys can be int's. 很可能因为基于整数的项查找是不明确的,因为dict键可以是int。 (Some custom use cases exist.) (存在一些自定义用例。)

Unfortunately, the documentation for dict hasn't been updated to reflect this (yet) and still says "Keys and values are iterated over in an arbitrary order which is non-random" . 不幸的是, dict文档还没有更新以反映这个(还),并且仍然说“键和值以任意顺序迭代,这是非随机的” Ironically, the collections.OrderedDict docs mention the new behaviour: 具有讽刺意味的是, collections.OrderedDict文档提到了新的行为:

Changed in version 3.6 : With the acceptance of PEP 468 , order is retained for keyword arguments passed to the OrderedDict constructor and its update() method. 版本3.6中已更改 :接受PEP 468后 ,将保留传递给OrderedDict构造函数及其update()方法的关键字参数的顺序。

And here's an article mentioning some more details about it : 这里有一篇文章提到了一些有关它的更多细节

A minor but useful internal improvement: Python 3.6 preserves the order of elements for more structures. 一个次要但有用的内部改进:Python 3.6保留了更多结构的元素顺序。 Keyword arguments passed to a function, attribute definitions in a class, and dictionaries all preserve the order of elements as they were defined. 传递给函数的关键字参数,类中的属性定义和字典都保留了元素定义时的顺序。

So if you're only writing code for Py36 onwards, you shouldn't need collections.OrderedDict unless you're using popitem , move_to_end or order-based equality. 因此,如果你只是为Py36编写代码,除非你使用popitemmove_to_end或基于顺序的相等,否则你不应该需要collections.OrderedDict

Example, in Python 2.7: 例如,在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}

And in Python 3.6: 在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

As of python 3.7 this is now a default behavior for dictionaries, it was an implementation detail in 3.6 that was adopted as of June 2018 :') 从python 3.7开始,这现在是字典的默认行为,它是截至2018年6月采用的3.6中的实现细节:')

the insertion-order preservation nature of dict objects has been declared to be an official part of the Python language spec. dict对象的插入顺序保存性质已被声明为Python语言规范的官方部分。

https://docs.python.org/3/whatsnew/3.7.html https://docs.python.org/3/whatsnew/3.7.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM