読者です 読者をやめる 読者になる 読者になる

odictでハマった話

Python

【2010/5/27更新】
doloopwhileさんにコメントをいただいたように、Python2.7のOrderedDictをバックポートしたordereddictモジュールを使うのがベストっぽいです。doloopwhileさん、情報ありがとうございます。


最近は「ソート済み辞書」ってやつをよく使うのだが、Python 2.6以前には標準ライブラリに含まれているものがない。なので、Python 2.6用にはodictを使って、

try:
    from collections import OrderedDict
except ImportError:
    from odict import odict as OrderedDict

って書くのが以前の僕のパターン。だが、Python 2.7のcollections.OrderedDictをキーワード引数に渡した場合、

>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d['spam'] = 1
>>> d['egg'] = 2
>>> d['ham'] = 3
>>> dict(**d)
{'egg': 2, 'ham': 3, 'spam': 1}

のように意図した通りに動くのだが、odictだと、

>>> from odict import odict as OrderedDict
>>> d = OrderedDict()
>>> d['spam'] = 1
>>> d['egg'] = 2
>>> d['ham'] = 3
>>> dict(**d)
{'egg': ['spam', 2, 'ham'], 'ham': ['egg', 3, nil], 'spam': [nil, 1, 'egg']}

のように大変困った結果になる。nilって何だよ・・・

仕方がないので、キーワード引数で関数を呼び出す場合は、

func(**orderd_dict)

から、

func(**dict(ordered_dict.items()))

に改めた。

こういった互換性を考慮する必要があるのかって問題もあるけど、もうしばらくはPython 2.6以前で動くものを書きたいような気がするし、運用面でもPython 2.7/Python 3系は時期尚早な気がする。

個人的には、Python 2.7の新しいioモジュールが気に入っていて、新規プロジェクトは2.7でやろうかなと思っていたけど、EPELにpython26パッケージが入ってきたのでちょっと悩むところ。Python 2.7で動かないライブラリも結構あるしなぁ。