Сделать встроенный lru_cache пропускать кеширование, когда функция возвращает NonePython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Сделать встроенный lru_cache пропускать кеширование, когда функция возвращает None

Сообщение Anonymous »

Вот упрощенная функция, для которой я пытаюсь добавить lru_cache для -

Код: Выделить всё

from functools import lru_cache, wraps

@lru_cache(maxsize=1000)
def validate_token(token):
if token % 3:
return None
return True

for x in range(1000):
validate_token(x)

print(validate_token.cache_info())
выходы -

Код: Выделить всё

CacheInfo(hits=0, misses=1000, maxsize=1000, currsize=1000)
Как мы видим, он также кэширует аргументы и возвращаемые значения для возврата None. В приведенном выше примере я хочу, чтобы размер кэша был равен 334, тогда мы возвращаем значения, отличные от None. В моем случае моя функция имеет большой номер. из аргументов может возвращать другое значение, если предыдущее значение было None. Поэтому я хочу избежать кэширования значений None.
Я хочу избежать изобретения велосипеда и повторной реализации lru_cache с нуля. . Есть ли хороший способ сделать это?
Вот некоторые из моих попыток -
1. Пытаюсь реализовать собственный кеш (что здесь не lru) -

Код: Выделить всё

from functools import wraps

# global cache object
MY_CACHE = {}

def get_func_hash(func):
# generates unique key for a function. TODO: fix what if function gets redefined?
return func.__module__ + '|' + func.__name__

def my_lru_cache(func):
name = get_func_hash(func)
if not name in MY_CACHE:
MY_CACHE[name] = {}
@wraps(func)
def function_wrapper(*args, **kwargs):
if tuple(args) in MY_CACHE[name]:
return MY_CACHE[name][tuple(args)]
value = func(*args, **kwargs)
if value is not None:
MY_CACHE[name][tuple(args)] = value
return value
return function_wrapper

@my_lru_cache
def validate_token(token):
if token % 3:
return None
return True

for x in range(1000):
validate_token(x)

print(get_func_hash(validate_token))
print(len(MY_CACHE[get_func_hash(validate_token)]))
выходы -

Код: Выделить всё

__main__|validate_token
334
2. Я понял, что lru_cache не выполняет кеширование при возникновении исключения внутри обернутой функции -

Код: Выделить всё

from functools import wraps, lru_cache

def my_lru_cache(func):
@wraps(func)
@lru_cache(maxsize=1000)
def function_wrapper(*args, **kwargs):
value = func(*args, **kwargs)
if value is None:
# TODO: change this to a custom exception
raise KeyError
return value
return function_wrapper

def handle_exception(func):
@wraps(func)
def function_wrapper(*args, **kwargs):
try:
value = func(*args, **kwargs)
return value
except KeyError:
return None
return function_wrapper

@handle_exception
@my_lru_cache
def validate_token(token):
if token % 3:
return None
return True

for x in range(1000):
validate_token(x)

print(validate_token.__wrapped__.cache_info())
выходы -

Код: Выделить всё

CacheInfo(hits=0, misses=334, maxsize=1000, currsize=334)
Выше правильно кэшируются только значения 334, но необходимо дважды обернуть функцию и получить доступ к кэшу_info странным образом func.__wrapped__.cache_info()
code>.
Как мне лучше добиться отсутствия кэширования, когда значения None(или определенные) возвращаются с использованием встроенного декоратора lru_cache в Pythonic путь?

Подробнее здесь: https://stackoverflow.com/questions/711 ... turns-none
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»