【问题标题】:Python OrderedDict iterationPython OrderedDict 迭代
【发布时间】:2013-05-09 08:14:48
【问题描述】:

为什么我的 python OrderedDict 被“乱序”初始化?

这里的解决方案没有解释那么有趣。这里有些东西我只是不明白,也许扩展会帮助其他人和我。

>>> 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

【问题讨论】:

标签: python ordereddictionary


【解决方案1】:

来自the docs

OrderedDict 构造函数和update() 方法都接受关键字参数,但它们的顺序丢失了,因为 Python 的函数调用语义使用常规无序字典传入关键字参数。

所以初始化失去了顺序,因为它基本上是用**kwargs调用构造函数。

编辑:解决方案(不仅仅是解释)而言——正如in a comment by the 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

这是因为它只得到一个参数,一个列表。

【讨论】:

  • 这就是为什么它有效:OrderedDict([('s',(1,2)),('p',(3,4)),('a',(5,6 )),('m',(7,8))] 在这种情况下,构造函数得到一个参数,一个 [list] 谢谢
  • 这是用 Python 3.6 解决的吧?来自文档 - 在 3.6 版中更改:在接受 PEP 468 后,为传递给 OrderedDict 构造函数及其 update() 方法的关键字参数保留顺序。
  • @chris-krycho,不正确的订单稍后会保留对吗?
【解决方案2】:

@Chris Krycho 很好地解释了失败的原因。

如果您查看 OrderedDict 的 repr(),您会得到一个提示,即如何从一开始就赋予顺序:您需要使用 (key, value) 对的列表来保留由列表。

这是我之前做过的一个:

>>> 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']
>>> 

(碰巧在 Python v3.3.0 中,spam 的原始示例从一开始就保持键的原始顺序。我更改为 spamher 来解决这个问题。

【讨论】:

    【解决方案3】:

    正如 other answers 所提到的,尝试将 dict 传递给 OrderedDict 或使用关键字参数不会保留顺序。不过,传入元组有点难看,这就是 Python。应该很漂亮。

    您可以在一个类上ab使用__getitem__,以获得类似dict的语法来创建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()
    

    现在您可以使用类似 dict 的语法来创建 OrderedDict:

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

    这是可行的,因为在方括号内,Python 创建了 slice 文字,如果你稍微眯一下眼,它恰好看起来像 dict 语法。

    OD 类可以从错误检查中受益,但这演示了它是如何工作的。

    【讨论】:

      猜你喜欢
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 2015-09-28
      • 2021-01-30
      • 2015-09-11
      • 1970-01-01
      • 2021-05-05
      相关资源
      最近更新 更多