関数オブジェクトを辞書キーとして使用しています。これらの関数の結果をキャッシュする必要があるため、これを行っています。これは大まかに私が使用しているコードです:
# module cache.py:
calculation_cache = {}
def cached(func):
# func takes input as argument
def new_function(input):
try:
result = calculation_cache[(func, input)]
except KeyError:
result = func(input)
calculation_cache[(func, input)] = result
return result
return new_function
# module stuff.py
@cached
def func(s):
# do something time-consuming to s
# ...
return result
func.__module__ + func.__name__
の代わりに使用することもできますがfunc
、func
問題なく動作する場合は、名前の競合が発生する可能性があるため、むしろ使用したいと思います (たとえば、lambda
関数、ネストされた関数、または同じ名前の別の関数に置き換えられた関数など)。
これは問題なく動作するように見えますが、テストが難しい状況で問題が発生する可能性があると思われます。
たとえば、何らかの理由で関数が削除され、別の関数がそのメモリ空間を再利用していることを懸念しています。この場合、私のキャッシュは無効になりますが、それは認識されません。これは正当な懸念事項ですか?もしそうなら、それに対処する方法はありますか?
関数を削除できますか? モジュールをリロードすると、関数が新しいアドレスに移動しますか (したがって、そのハッシュ値が変更され、新しい関数のために古いメモリ アドレスが解放されます)? 誰かが (何らかの奇妙な理由で) モジュールで定義された関数を単純に削除することはできますか?
で明示的に定義された関数でのみこれを行うことが安全である場合はdef
、例外をデコレータとして使用することを禁止できますcached
(強制する方法はわかりませんが、cached
docstring で文書化することはできます)。