2013-05-14 105 views
29

爲什麼我的python OrderedDict得到'失序'初始化?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 
+10

「kwargs」未訂購。 – georg

+0

[轉換字典爲OrderedDict]可能的重複(http://stackoverflow.com/questions/15711755/converting-dict-to-ordereddict) –

回答

36

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 

這是因爲它只能得到一個參數,一個列表。

+5

所以這就是爲什麼這個工程: OrderedDict([('s',(1 ,(''',(5,6)),('',(7,8))] 在這種情況下,構造函數得到一個參數,[列表] 謝謝 –

+0

這是用Python 3.6解決的問題?從文檔 - 在版本3.6中更改:隨着PEP 468的接受,保留了傳遞給OrderedDict構造函數和其更新的關鍵字參數的順序()方法 – gpk27

+0

@ chris-krycho,不合時宜的訂單會在以後保存嗎? – gpk27

17

@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 3.3.0你原來的spam例如保持其的鑰匙,從一開始就以其原始順序我改spamher得到。這一點)。

4

正如otheranswers所提到的,嘗試將字典傳遞給OrderedDict或使用關鍵字參數不會保留順序。傳遞元組有點難看,而這就是Python。它應該是美麗的。

您可以 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() 

現在你可以使用類似字典的語法來創建一個OrderedDict:

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

這工作,因爲方括號中,巨蟒創造slice文字,碰巧看起來像字典語法,如果你稍微斜視一下。

OD類可以從錯誤檢查中受益,但是這證明了它如何工作。