Является ли FORZENSET адекватным для кэширования симметричных входных данных в Python Dict?
Вопрос
Название более или менее говорит все это:
У меня есть функция, которая принимает симметричный вход в два аргумента, например, что-то вроде
def f(a1, a2):
return heavy_stuff(abs(a1 - a2))
Теперь я хочу внести метод кэширования. Было ли это правильно / питон / разумно эффективно делать что-то вроде этого:
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 Array; Вот почему я обернутую их в кортеже каждый.
Решение
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
вероятно, хорошо; Хотя (если компоненты x
а также y
сопоставимы, как и hashable - то есть это не будет работать со сложными числами), вы можете рассмотреть
ta1 = tuple(a1)
ta2 = tuple(a2)
if ta1 > ta2: key = ta1, ta2
else: key = ta2, ta1
Относительная производительность зависит от стоимости сравнения, против качества перемешивания, предметов в a1
а также a2
. Отказ Различия, вероятно, будут незначительными, в любом случае.