简体   繁体   English

Python OrderedDict迭代

[英]Python OrderedDict iteration

Why does my python OrderedDict get initialized 'out of order'? 为什么我的python OrderedDict被初始化为'乱序'?

The solution here is less intriguing than the explanation. 这里的解决方案不如解释那么有趣。 There's something here I just don't get, and perhaps an expanation would help others as well as me. 这里有些东西,我只是没有得到,也许扩张会帮助别人和我。

>>> from collections import OrderedDict

>>> spam = OrderedDict(s = (1, 2), p = (3, 4), a = (5, 6), m = (7, 8))

>>> spam
OrderedDict([('a', (5, 6)), ('p', (3, 4)), ('s', (1, 2)), ('m', (7, 8))])

>>> for key in spam.keys():
...    print key    
...
#  this is 'ordered' but not the order I wanted....
a
p
s
m

# I was expecting (and wanting):
s
p
a
m

From 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的函数使用常规无序字典调用语义传入关键字参数。

So initialization loses the ordering, because it's basically calling a constructor with **kwargs . 所以初始化会丢失排序,因为它基本上是用**kwargs调用构造函数。

Edit: In terms of a solution (not just an explanation )—as pointed out in a comment by the OP , passing in a single list of tuples will work: 编辑:解决方案而言 (不仅仅是解释 ) - 如OP的评论所指出的那样,传入单个元组列表起作用:

>>> from collections import OrderedDict
>>> spam = OrderedDict([('s',(1,2)),('p',(3,4)),('a',(5,6)),('m',(7,8))])
>>> for key in spam:
...     print(key)
...
s
p
a
m
>>> for key in spam.keys():
...     print(key)
...
s
p
a
m

This is because it's only getting a single argument, a list. 这是因为它只获得一个参数,一个列表。

@Chris Krycho gave a good explanation of why things fail. @Chris Krycho很好地解释了为什么失败了。

If you look at the repr() of an OrderedDict you get a hint at how to impart order from the beginning: You need to use a list of (key, value) pairs to preserve the order of the keys given by the list. 如果你查看OrderedDict的repr(),你会得到一个如何从头开始传递顺序的提示:你需要使用(键,值)对的列表来保持列表给出的键的顺序。

Here's one I did earlier: 这是我之前做的一个:

>>> from collections import OrderedDict
>>> spamher = OrderedDict(s=6, p=5, a=4, m=3, h=2, e=1, r=0)
>>> spamher
OrderedDict([('h', 2), ('m', 3), ('r', 0), ('s', 6), ('p', 5), ('a', 4), ('e', 1)])
>>> 
>>> list(spamher.keys())
['h', 'm', 'r', 's', 'p', 'a', 'e']
>>> 
>>> spamher = OrderedDict([('s', 6), ('p', 5), ('a', 4), ('m', 3), ('h', 2), ('e', 1), ('r', 0)])
>>> list(spamher.keys())
['s', 'p', 'a', 'm', 'h', 'e', 'r']
>>> 

(It just so happened that in Python v3.3.0 your original example of spam kept the keys in their original order from the outset. I changed to spamher to get arounf this). (正巧是在Python 3.3.0你原来的例子spam保存在从一开始就它们原来的顺序按键。我改spamher得到arounf这一点)。

As the other answers have mentioned, trying to pass a dict to OrderedDict or using keyword arguments doesn't preserve the order. 正如其他 答案所提到的,尝试将dict传递给OrderedDict或使用关键字参数不会保留顺序。 Passing in tuples is kinda ugly, though, and this is Python. 传递元组有点难看,这就是Python。 It should be beautiful. 它应该是美丽的。

You can ab use __getitem__ on a class in order to have dict-like syntax for creating OrderedDict "literals": 您可以使用 AB __getitem__上一类以具有类似字典的语法创建OrderedDict“文字”:

from collections import OrderedDict
class OD(object):
    """This class provides a nice way to create OrderedDict "literals"."""
    def __getitem__(self, slices):
        if not isinstance(slices, tuple):
            slices = slices,
        return OrderedDict((slice.start, slice.stop) for slice in slices)
# Create a single instance; we don't ever need to refer to the class.
OD = OD()

Now you can use dict-like syntax to create an OrderedDict: 现在您可以使用类似dict的语法来创建OrderedDict:

spam = OD['s': (1, 2), 
          'p': (3, 4), 
          'a': (5, 6), 
          'm': (7, 8)]
assert(''.join(spam.keys()) == 'spam')

This works because inside the square brackets, Python creates slice literals, which happen to look like dict syntax if you squint a little. 这是有效的,因为在方括号内,Python创建切片文字,如果你稍微眯一下,它恰好看起来像dict语法。

The OD class could benefit from error checking, but this demonstrates how it can work. OD类可以从错误检查中受益,但这表明它是如何工作的。

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

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