Python3.6時点では辞書データはリストと異なり要素の順番は不定です。辞書型のデータ構造で順番を維持させたい場合はcollections.OrderedDict()を使います。このメソッドで生成される順序付き辞書(Ordered dictionary)は、データが登録された順序が保持されます。今回はこのOrderedDict()メソッドの使い方についてまとめます。
(2018.7.1更新) Python3.7から辞書データの順番が保持されることが仕様化されました。
確認した環境
OS: Ubuntu 16.04LTS
Python: ver3.6.4
辞書における要素の順番について
Python3.6から辞書の挿入順番が保持される実装が追加されていますが、まだ言語(Python)としての仕様化までには至っていません。公式ドキュメントにも「それに頼るべきではない」と記載があります。正式にはPython3.7からサポートされるとの議論がありますが、今は順序付き辞書(Ordered dictionary)を使うべきだそうです。
確認してみると、、確かにPthon3.5とPython3.6で挙動が変わっています。
(2018.7.1更新)Python3.7がリリースされ、辞書の挿入順番が保持されることが正式に仕様化されました。
バージョン 3.7 で変更: Dictionary order is guaranteed to be insertion order. This behavior was implementation detail of CPython from 3.6.
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> dic = {}
>>> dic['a'] = 1
>>> dic['b'] = 2
>>> dic['c'] = 3
>>> dic['d'] = 4
>>> dic
{'d': 4, 'a': 1, 'c': 3, 'b': 2}
>>> for k, v in dic.items():
... print(k, v)
...
d 4
a 1
c 3
b 2
>>>
Python 3.6.4 |Anaconda custom (64-bit)| (default, Dec 21 2017, 21:42:08)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> dic = {}
>>> dic['a'] = 1
>>> dic['b'] = 2
>>> dic['c'] = 3
>>> dic['d'] = 4
>>> dic
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> for k, v in dic.items():
... print(k, v)
...
a 1
b 2
c 3
d 4
>>>
順序付き辞書(Ordered dictionary)の使い方
順序付き辞書 (ordered dictionary) は以下で定義されます。
class collections.OrderedDict([items])
このメソッドはデータが挿入された順序を保持します。順序付き辞書のデータを順次読み出すと、追加された順番に出力されます。
>>> from collections import OrderedDict #collectionsモジュールをインポート
>>> dic = OrderedDict() #順序付き辞書を定義
>>> dic['a'] = 4
>>> dic['b'] = 3
>>> dic['c'] = 2
>>> dic['d'] = 1
>>> dic
#順番が保持されているか確認
>>> for k, v in dic.items():
... print(k, v)
...
a 4
b 3
c 2
d 1
既存のキーの値を上書き更新した場合は順番は変わらないままです。
>>> dic['b'] = 7 #キーが'b'の値を更新
>>> for k, v in dic.items():
... print(k, v)
...
a 4
b 7
c 2
d 1
また、キーを削除して再度追加した場合は、順番の最後に移動します。
#キーが'b'のデータを削除
>>> del dic['b']
#削除されていることを確認
>>> dic
OrderedDict([('a', 4), ('c', 2), ('d', 1)])
#同じキーのデータを再度挿入
>>> dic['b'] = 10
#上記で追加したデータは最後に移動
>>> for k, v in dic.items():
... print(k, v)
...
a 4
c 2
d 1
b 10
まとめ
- Python3.6では辞書に順番を保持する実装が追加されたが、まだ言語として仕様化されていません。よって、データの挿入順番を保持したい場合は、順序付き辞書(Ordered dictionary)を使います。
(将来(Python3.7?)では対応されるかも) - Python3.7から挿入順番を保持することが仕様化されました。(旧バージョンとの互換を考えるとしばらくはOrderedDictを使ったほうがよいかも?)