2015年12月7日

collections.OrderedDict

collectionsライブラリで定義されている collections.OrderedDict を紹介します。
(OrderedDict は Python 3.1 で追加されました。さらに 3.2 と 3.5 で若干の機能追加が行われています。)

dict の key の順序はハッシュ値により決定されます。つまり使う側から見ると、順序は制御不可能です。
OrderedDict は dict を継承したクラスで、key の順序が登録した順になります。
dict と OrderedDict の動作を比較します。

# ビルトインのdict。順序はハッシュ値依存
>>> d = dict()
>>> d['A'] = 10
>>> d['B'] = 11
>>> d['C'] = 12
>>> d
{'C': 12, 'B': 11, 'A': 10}

# OrderedDict。順序は登録順
>>> from collections import OrderedDict
>>> od = OrderedDict()
>>> od['A'] = 10
>>> od['B'] = 11
>>> od['C'] = 12
>>> od
OrderedDict([('A', 10), ('B', 11), ('C', 12)])


OrderedDict は dict を継承して作られています。このため、dict でできることは全て OrderedDict でもできるようになっています。この辺り、コンテナ型を自作する場合には参考にしたい所ですね。
>>> issubclass(OrderedDict, dict)
True

>>> isinstance(od, dict)
True


OrderedDict の使い所は当然ながら、データの順序を保ちつつ dict でデータを管理するようなケースです。設定ファイルの読み込み等で最もよく使われると思います。
以下は、tuple の順序を変えずに OrderedDict へ代入する例です。
# 順序を維持したいデータ
>>> settings = (
...     ('protcol', 'TCP'),
...     ('IP', '192.168.0.1'),
...     ('port', 60000),
... )

# OrderedDictへ代入
>>> od = OrderedDict(settings)
>>> od
OrderedDict([('protcol', 'TCP'), ('IP', '192.168.0.1'), ('port', 60000)])


また、通常の dict から key の大小で並び替えた OrderedDict を作るには以下のようにします。(当然、dict の key は大小比較が可能である必要があります。)
# 通常のdict。順序はハッシュ値依存
>>> d = dict()
>>> d['A'] = 10
>>> d['B'] = 11
>>> d['C'] = 12

# key順でOrderedDictへ代入
>>> od = OrderedDict(sorted(d.items()))
>>> od
OrderedDict([('A', 10), ('B', 11), ('C', 12)])

0 件のコメント:

コメントを投稿