Как хэш * args ** kwargs для кеша функции?

Я работаю с xlwt, который имеет ограничение 4k на то, сколько стилей может быть определено в документе excel.

Обычно создаются такие стили:

style = xlwt.easyxf("font: bold 1")

Что я просто заменил на

def cached_easyxf(self, format):
    return self._cache.setdefault(format, xlwt.easyxf(format))

Что работает отлично. Теперь я выяснил, что мне нужно иногда передавать аргументы ключевых слов, которые заставляли меня думать: как я должен хэшировать подпись args/kwargs?

Должен ли я создать ключ кеша на основе str (значение)? Соленый огурец? Что наиболее надежное?

В моей ситуации это похоже на то, что я могу просто преобразовать ключ/значения в строки и добавить его к моим ключам... но теперь мне любопытно об общем способе справиться с этим, например, с нераскрывающимися типами, например arg=[1, 2, 3]

def cached_call(*args, **kwargs):
    return cache.get(what_here)
cached_call('hello')
cached_call([1, 2, 3], {'1': True})

Ответ 1

Вот техника, используемая в functools.lru_cache():

kwd_mark = object()     # sentinel for separating args from kwargs

def cached_call(*args, **kwargs):
    key = args + (kwd_mark,) + tuple(sorted(kwargs.items()))
    return cache.get(key)

Обратите внимание, что приведенный выше код обрабатывает аргументы ключевого слова, но не пытается обрабатывать недопустимые значения, например списки. Ваша идея использовать страницу списка является разумным началом. Для заданных объектов вам нужно сначала отсортировать записи, str(sorted(someset)). Другие объекты могут не иметь полезного __repr__ или __str__ (то есть они могут отображать только тип объекта и местоположение в памяти). Таким образом, обработка произвольных несвязанных аргументов требует тщательного рассмотрения каждого типа объекта.