У меня есть несколько классов с методами compute
, которые принимают некоторые (возможно, очень разные) аргументы, выполняют вычисления и возвращают результат. Я хотел создать базовый класс, который позволял бы кэшировать результаты и извлекать их из кэша.
Простой пример:
import hashlib
class Base():
def compute(self, *args):
raise NotImplementedError
def compute_with_cache(self, *args):
hash_ = self._hash_anything(args)
try:
return self.cache[hash_]
except KeyError:
result = self.compute(*args)
self.cache[hash_] = result
return result
@staticmethod
def _hash_anything(args):
return hashlib.md5(str(args).encode('utf-8')).hexdigest()
class SpecificComputation(Base):
cache = {}
def compute(self, some_arg, other_arg):
result = ... # performs possibly time consuming operations
return result
Это решение почему-то работает, но имеет два (может быть, больше? ) проблемы:
- Предполагается, что
str(args)
отличается для каждого различного набора args
, это обычно справедливо для простых структур данных, таких как списки или числа, но завершится ошибкой, например, для экземпляров классов без Однозначные строковые представления - Требуется приведение к строке и вычисление md5, и это занимает время
Первая проблема может быть решена с помощью pickle
, но она замедлится еще больше.
Итак, вопрос в том, как реализовать _hash_anything
таким образом, чтобы:
Есть ли какое-либо общее решение, предполагающее, что args
может содержать практически что-нибудь?
Если нет, возможно, существует эффективный при условии решения args
содержат только простые структуры данных (кортежи целых чисел, списки строк и т. Д. c) или np.arrays?