2019年7月20日

OrderedDict の行く末

こちら述べたように、Python 3.7 から、dict の要素順が挿入順であることが保証されるようになりました。
Python には元々 collectionsモジュールに OrderedDict という挿入順を保つ辞書型が用意されていました。dict が挿入順となった Python 3.7 以降では、OrderedDictの使い道はなくなってしまうのでしょうか?
実はそうではありません。OrderedDict と dict は基本的な性質に違いがあります。

まず、OrederDict の基本です。要素の挿入順が保持されます。

>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d[1] = 1
>>> d[2] = 2
>>> d
OrderedDict([(1, 1), (2, 2)])  # 1, 2の順
この挿入順は、そのまま同値判定にも使用されます。
つまり、要素が同じでも挿入順が異なれば、OrderedDict としては異なる値として判定されます。
>>> rd = OrderedDict()
>>> rd[2] = 2
>>> rd[1] = 1
>>> rd
OrderedDict([(2, 2), (1, 1)])  # 2, 1の順

# 挿入順が異なるので、異なる値となる
>>> d == rd
False

OrderedDict の同値判定を敢えて書けば、以下のようになるでしょうか。
def eq(lhs, rhs):
    return (len(lhs) == len(rhs)) and
            all(i == j for i, j in zip(lhs.items(), rhs.items()))


一方 dict の場合、挿入順は要素の並び順だけの話で、同値判定には使用されません。
>>> d = dict()
>>> d[1] = 1
>>> d[2] = 2
>>> d
{1: 1, 2: 2}  # 1, 2の順

>>> rd = dict()
>>> rd[2] = 2
>>> rd[1] = 1
>>> rd
{2: 2, 1: 1}  # 2, 1の順

# 挿入順は異なるが、同じ値
>>> d == rd
True

dict の同値判定を敢えて書けば、以下のようになるでしょうか。
def eq(lhs, rhs):
    if len(lhs) == len(rhs):
        try:
            return all(lhs[k] == rhs[k] for k in lhs)
        except KeyError:
            pass
    return False



OrderedDict には基本的な仕様で dict と異なるところがあるので、今後も OrderedDict が廃止になったり、非推奨に降格になることは無いと思われます。

0 件のコメント:

コメントを投稿