なぜ私の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
ドキュメント から:
OrderedDictコンストラクターと
update()
メソッドはどちらもキーワード引数を受け入れますが、Pythonの関数は通常の順序付けされていない辞書を使用してセマンティクスのパスインキーワード引数を呼び出すため、それらの順序は失われます。
したがって、初期化は基本的に**kwargs
でコンストラクターを呼び出しているため、順序付けが失われます。
Edit:solutionの観点から(explanation)-指摘されているように OPによるコメントで 、タプルの単一のリストを渡すwill動作:
>>> 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
これは、1つの引数、リストのみを取得しているためです。
@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
に変更しました。これを得るために)。
otheranswers で述べたように、dictをOrderedDictに渡そうとしても、キーワード引数を使用しても順序は維持されません。ただし、タプルを渡すことはちょっと見苦しく、これはPythonです。それは美しいはずです。
あなたはできる ab使用する __getitem__
は、OrderedDict "literals"を作成するためのdictのような構文を持つためのクラスです。
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-like構文を使用してOrderedDictを作成できます。
spam = OD['s': (1, 2),
'p': (3, 4),
'a': (5, 6),
'm': (7, 8)]
assert(''.join(spam.keys()) == 'spam')
これは、角括弧内でPythonが slice リテラルを作成するため、少し目を細めると辞書構文のように見えるためです。
OD
クラスはエラーチェックの恩恵を受ける可能性がありますが、これはどのように機能するかを示しています。