1

タイトルは多かれ少なかれそれをすべて言います:

対称入力を 2 つの引数で受け取る関数があります。たとえば、次のようなものです。

def f(a1, a2):
    return heavy_stuff(abs(a1 - a2))

ここで、キャッシングの方法をいくつか紹介したいと思います。次のようなことを行うのは正しい/ pythonic /合理的に効率的でしょうか:

cache = {}
def g(a1, a2):
    fs =frozenset((tuple(a1), tuple(a2)))
    if fs not in cache:
        cache[fs] = f(a1, a2)
    return cache[fs]

それとももっと良い方法があるでしょうか?

編集: a1 と a2 は、numpy 配列の行である可能性があります。そのため、それらをそれぞれタプルでラップします。

4

1 に答える 1

2

Python は常に、関数に渡すすべての引数を計算してから、関数を呼び出します。言い換えれば、他のほとんどの言語と同様に、Python はその評価において「積極的」です (今日の主な例外はおそらく Haskell ですが、それは役に立ちません;-)。

したがって、キャッシングにsetdefault非常に不適切なアプローチです。あなたがするたびに

cache.setdefault(akey, f(x, y))

最初にを呼び出しf(x, y)、そのすべての計算コストを使用してから、その計算の結果フロアにドロップする可能性があります。これにより、キャッシングが完全に無効になります。

むしろ、常に次のようにしてください。

akey = whatever(x, y)
if akey not in cache:
    cache[akey] = f(x, y)
return cache[akey]

fなど -- 他にも考えられるイディオムがいくつかありますNone

result = cache.get(akey)
if result is None:
    result = cache[akey] = f(x, y)
return result

whatever鍵の計算に何が適切であるかという二次的な問題については、それが対称であることを知っていれば、おそらく問題fないと思います。frozensetただし ( と のコンポーネントxy比較可能であり、ハッシュ可能である場合、つまり、複素数では機能しない場合)、考慮したい場合があります

ta1 = tuple(a1)
ta2 = tuple(a2)
if ta1 > ta2: key = ta1, ta2
else: key = ta2, ta1

a1相対的なパフォーマンスは、との項目を比較するコストとハッシュ化するコストに依存しますa2。とにかく、違いは小さい可能性があります。

于 2010-04-03T22:36:22.773 に答える