简体   繁体   English

OrderedDict没有订购?

[英]OrderedDict Isn't Ordered?

I'm trying to use an OrderedDict , but it keeps being created out of order. 我正在尝试使用OrderedDict ,但它仍然不按顺序创建。 For example, 例如,

from collections import OrderedDict
OrderedDict(a=1,b=2,c=3)

yields 产量

OrderedDict([('a', 1), ('c', 3), ('b', 2)])

rather than the expected 而不是预期的

OrderedDict([('a', 1), ('b', 2), ('c', 3)])

How can I make sure it's created in the proper order I intend? 我怎样才能确保按照我想要的正确顺序创建它?

collections.OrderedDict keeps track of the order in which elements were added to it. collections.OrderedDict跟踪元素添加到它的顺序。 This would work fine in a loop: 这在循环中可以正常工作:

c = collections.OrderedDict()
for a,b in zip('abc', (1,2,3)):
    c[a] = b

However, the expression OrderedDict(a=1,b=2,c=3) creates an OrderedDict by passing several keyword arguments to its constructor. 但是,表达式OrderedDict(a=1,b=2,c=3)通过将几个关键字参数传递给其构造函数来创建OrderedDict In Python 2.7, the order of keyword arguments is not guaranteed. 在Python 2.7中,不保证关键字参数的顺序。 If you want that, you'll have to move to Python 3.6, which implements PEP 468, Preserving the order of **kwargs in a function . 如果你想要,你将不得不转向Python 3.6,它实现了PEP 468, 保留了函数中** kwargs的顺序

The **kwargs syntax in a function definition indicates that the interpreter should collect all keyword arguments that do not correspond to other named parameters. 函数定义中的**kwargs语法指示解释器应收集与其他命名参数不对应的所有关键字参数。 However, Python does not preserved the order in which those collected keyword arguments were passed to the function. 但是,Python不保留将这些收集的关键字参数传递给函数的顺序。 In some contexts the order matters. 在某些情况下,订单很重要。 This PEP dictates that the collected keyword arguments be exposed in the function body as an ordered mapping. 此PEP规定收集的关键字参数作为有序映射在函数体中公开。

It's weird that it hasn't been mentioned already but the representation of OrderedDict shows you how to create it so that the order is kept: 奇怪的是它尚未被提及,但OrderedDict表示向您展示了如何创建它以便保持顺序:

OrderedDict([('a', 1), ('b', 2), ('c', 3)])

it's not meant as an obstacle that the representation is like that - it's because that representation can be used to create an identical ordered OrderedDict . 它并不意味着表示就像是一个障碍 - 这是因为该表示可以用来创建一个相同的有序OrderedDict


Just for completeness (it has been mentioned already), the order is lost because OrderedDict(a=1, b=2, c=3) catches these arguments as **kwargs , which is a normal unordered- dict . 为了完整性(已经提到过),由于OrderedDict(a=1, b=2, c=3)这些参数捕获为**kwargs ,这是一个正常的无序dict ,因此订单会丢失。 At least until python 3.6 came along and made the promise that the order of the kwargs will be kept when you pass it in as you did: 至少直到python 3.6出现并承诺 ,当你传递它时,将保留kwargs的顺序:

What's New In Python 3.6 Python 3.6中的新功能

PEP 468: Preserving Keyword Argument Order PEP 468:保留关键字参数顺序

**kwargs in a function signature is now guaranteed to be an insertion-order-preserving mapping. **kwargs函数签名中的**kwargs现在保证是一个插入顺序保留映射。

Read the docs : 阅读文档

The OrderedDict constructor and update() method both accept keyword arguments, but their order is lost because Python's function call semantics pass-in keyword arguments using a regular unordered dictionary. OrderedDict构造函数和update()方法都接受关键字参数,但它们的顺序丢失,因为Python的函数使用常规无序字典调用语义传入关键字参数。

You must pass the input as a sequence of tuples (or an existing ordered dict type) to preserve ordering. 必须将输入作为一系列元组(或现有的有序dict类型)传递以保持排序。

Note that Python 3.6 now provides a guarantee that keyword arguments are passed in the same order they appear in the code (from left to right) , thanks to PEP 468 , so on Python 3.6 and later, your code will just work. 请注意,Python 3.6现在可以保证关键字参数按照它们在代码中出现的顺序(从左到右)传递,这要归功于PEP 468 ,因此在Python 3.6及更高版本中,您的代码才能正常工作。

That is because the keyword arguments (variable = value, ) that you pass will be consolidated into a Python dictionary first. 这是因为您传递的关键字参数(variable = value, )将首先合并到Python字典中。 And Python dictionaries are unordered. Python字典是无序的。 kwds will be that dictionary as you can see in the Init signature. 你可以在Init签名中看到kwds那个字典。

Init signature: OrderedDict(self, *args, **kwds)

This is how the OrderedDict will be initialized internally when you pass the keyword arguments: 这是在传递关键字参数时内部初始化OrderedDict的方式

for key, value in kwds.items():
   self[key] = value

Since kwds is unordered, you will get an unordered OrderedDict. 由于kwds是无序的,你将得到一个无序的OrderedDict。

You may create the ordered dict like so: 您可以像这样创建有序的dict:

from collections import OrderedDict
from string import ascii_lowercase

d = OrderedDict()
for a,b in enumerate(ascii_lowercase[:3], 1):
    d[b] = a

Or: 要么:

n=3
d = OrderedDict(zip(ascii_lowercase[:n], range(1,n+1))) 
print d 

Output: 输出:

OrderedDict([('a', 1), ('b', 2), ('c', 3)])

You can create the desired mapping by using sorted() : 您可以使用sorted()创建所需的映射:

dict = {"a":"some_value", "b":"other_value", "c":"foo"}
ordered = OrderedDict(sorted(dict.items(), key=lambda t: t[0]))

This sorts the items prior to passing them to the OrderedDict constructor. 这会在将项目传递给OrderedDict构造函数之前对其进行排序。

The key= section sets the sorting, and t[0] sorts by the dictionary key. key=部分设置排序, t[0]按字典键排序。

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

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