関数の戻り値をキャッシュする
ある関数について高速化を図るため、キャッシュ用の辞書型に引数-戻り値を保存して返す必要が出てきたとします。
最近では@lru_cacheデコレータがありますが、Python 3.2より前だと標準的なものはないので、自前でデコレータやラップ関数を作ることもありました。
さて、お手軽に辞書型に保存する自前ラップ関数を作ろうとしたとき、まず真っ先にsetdefaultが使えるかなと考えました。というのもsetdefaultはキーがなければ書込み、キーがあれば読み出すのですから、キャッシュ操作そのものだと思ったからです。
しかし次のような書き方では正常に動きませんでした。
def func(arg1, arg2, cache={}): key = (arg1, arg2) return cache.setdefault(key, _func(arg1, arg2)) def _func(arg1, arg2): ...
setdefaultより先に引数が実行されるので、これでは常に_funcが呼び出されてしまいます。
次のようにすればor以降は評価されないので、_funcが呼び出されるのは最初の1回だけになります。
def func(arg1, arg2, cache={}): key = (arg1, arg2) return cache.get(key) or cache.setdefault(key, _func(arg1, arg2))