有时,参数可以采用简单的可散列类型或复杂的不可散列类型,而无需直接转换为可散列,正如当前答案所建议的那样。在这种情况下,可能仍然希望将缓存用于(可能更常见的)可散列类型的情况,而不使用缓存或在不可散列的情况下出错 - 只需调用底层函数。
这会忽略错误并通常适用于任何可散列类型:
import functools
def ignore_unhashable(func):
uncached = func.__wrapped__
attributes = functools.WRAPPER_ASSIGNMENTS + ('cache_info', 'cache_clear')
@functools.wraps(func, assigned=attributes)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except TypeError as error:
if 'unhashable type' in str(error):
return uncached(*args, **kwargs)
raise
wrapper.__uncached__ = uncached
return wrapper
使用和测试:
@ignore_unhashable
@functools.lru_cache()
def example_func(lst):
return sum(lst) + max(lst) + min(lst)
example_func([1, 2]) # 6
example_func.cache_info()
# CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)
example_func((1, 2)) # 6
example_func.cache_info()
# CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
example_func((1, 2)) # 6
example_func.cache_info()
# CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
我花了一点时间来理解它,但example_func.__wrapped__ 是 lru_cache 的版本,example_func.__uncached__ 是原始版本。