メインコンテンツへスキップ

Pythonの辞書に dot notation でアクセスする

NOTE
この記事は最終更新日から1年以上が経過しています。内容が古くなっている可能性があります。

Javascript のハッシュマップはドット・ノーテーション ( dot notation )でアイテムにアクセスできますよね。でも Python の辞書ではそれができません。できたら便利だなーと考えていたらひらめいたので、 dict クラスを継承した dict2 クラスを作りました。

class dict2(dict): 
    def __init__(self, *args, **kwargs): 
        super().__init__(*args, **kwargs) 
        self.__dict__ = self 

コンストラクタ init() をオーバーライドして self.dict に self を代入する行を加えました。 ただそれだけです。

dict はオブジェクトの書き込み可能なアトリビュートを格納するために使用される辞書またはその他のマッピングオブジェクトです。 self はまさに dict を継承したマッピングオブジェクトなので、アトリビュートを格納する dict に self を代入すれば、ドット・ノーテーションでアトリビュートとして辞書のアイテムにアクセスできるようになるってわけです。

ピンとこなくても、とりあえず動作を見てみましょう。

まず IPython を起動したら、上の dict2 クラスのコードをコピペします。必ずしも IPython である必要はありませんが、解説に便利なので使います。

$ ipython
Python 3.5.2

In [1]: # ここにコピペして[Enter]

こんな感じで、 Javascript のようにアトリビュートにキー名を書くとバリューが返ります。

In [2]: d2 = dict2({'abc': 123})
In [3]: d2.abc
Out[3]: 123

In [4]: d2.update({'abc': 456})
In [5]: d2.abc
Out[5]: 456

ネストすればチェインもできます。

In [6]: d2.update({'ijk': dict2({'xyz': 789})})
In [7]: d2
Out[7]: {'abc': 456, 'ijk': {'xyz': 789}}

In [8]: d2.ijk.xyz
Out[8]: 789

さらに、ドット・ノーテーションで辞書のアイテムを追加することもできます。

In [9]: d2.uvw = 'foobar'
In [10]: d2['uvw']
Out[10]: 'foobar'

もちろん、ドット・ノーテーションで辞書のアイテムを更新できます。

In [11]: d2.abc = 321
In [12]: d2['abc']
Out[12]: 321

万能すぎる…

なんだろう、このダクトテープとか結束バンドを使った修理に似た感覚は。

注意点としては、キーに予約語とか演算子の記号とか数値リテラルとか変数名に使えない文字列が入ると、辞書のキーとしては問題ないですが、ドット・ノーテーションだとシンタックスエラーになります。あと、すでにあるアトリビュート名とキーが衝突すると上書きされるので気をつけましょう。そういう諸々をエラーにしたいときは、 init() に加えて setitem() とか update() とかもオーバーライドしてバリデーションすればいいんじゃないですかね。他にも副作用があるかもしれません。

関連記事

Python でシングルトンパターンを実装する

生成されるクラスインスタンスを常に一つにするシングルトンパターンを Python で実装します。 Python は Java みたいに “private static” みたいな修飾ができないし、どこで初期化すればいいのかもちょっと考える必要があります。