ASPN : Python Cookbook : emulate collections.defaultdict

Python2.5では標準モジュールにdefaultdictという辞書型のクラスがあってキーが存在しない時のデフォルト値を設定できる。
プチ便利そうなので何かの出現回数のカウントアップとかはこれで。
で、2.4以前でも同じことをするためのレシピ。

調べたこと

  • defaultdict
  • __reduce__(self)
  • __copy__(self)/__deepcopy__(self,memo)
  • copyモジュール
  • __repr__(self)

defaultdict

collectionsモジュールのクラスで、キーが存在しない時のデフォルト値を設定できる辞書。
コンストラクタにデフォルト値を生成するfactory関数を渡す。
0をデフォルト値にしたくばdefaultdict(int)で良し。int()が0を返すので。
factory関数はdefaultdictの__missing__(self,key)メソッドから呼ばれる。

__reduce__(self)

pickle化のヒントを与える特殊メソッド。
pickle化時に呼び出されるらしい。オブジェクト名文字列かタプルを返す。
タプルにはリストとか辞書の要素などを入れる。

__copy__(self)/__deepcopy__(self,memo)

コピーを実装する特殊メソッド。
deepcopyには「現在のコピー過程ですでにコピーされたオブジェクトからなる」メモ辞書を渡す。
この辞書で再帰ループを避けるように、とのことらしい。

コピーの簡単なイディオムはtypeを使って新しいインスタンスを作るというもの。

return type(instance)(arg)

このレシピではコンストラクタの中で

dict.__init__(self, *a, **kw)

というのを入れておき、

return type(self)(self.default_factory, self)

とすることで中の要素もコピーできるようになってる。

copyモジュール

汎用のコピー操作をまとめたモジュール。

__repr__(self)

文字列を返す。オブジェクトから文字列への変換の時に呼ばれる特殊メソッド。
具体的にはrepr()組み込み関数と逆クォート表記での展開で呼ばれる。
対して__str__(self)はstr()とprint文で呼ばれる。
違いは、__repr__はオブジェクトを再生成するときに使えるようにPythonの式に似せるべきこと。