我想缓存一个以列表为参数的函数,但是当我尝试使用functools.lru_cache
装饰器时,它失败了。
import functools
@functools.lru_cache()
def example_func(lst):
return sum(lst) + max(lst) + min(lst)
print(example_func([1, 2]))
字符串
我想缓存一个以列表为参数的函数,但是当我尝试使用functools.lru_cache
装饰器时,它失败了。
import functools
@functools.lru_cache()
def example_func(lst):
return sum(lst) + max(lst) + min(lst)
print(example_func([1, 2]))
字符串
6条答案
按热度按时间jk9hmnmh1#
这会失败,因为列表是不可散列的。这会使Python很难知道缓存了哪些值。解决这个问题的一种方法是在将列表传递给缓存函数之前将它们转换为元组:因为元组是不可变的和可散列的,所以它们可以被缓存。
TL;DR
使用元组而不是列表:
字符串
b4lqfgs42#
它不应该抛出错误,而是在用户不知道的情况下在decorator中转换成可散列的形式。你可以通过像这样装饰你的函数来解决这个问题:
字符串
您可能希望在lru_cache之后使用另一个装饰器,以确保函数的输出不是元组,而是列表,因为现在它将返回元组。
b4qexyjb3#
有时候,一个参数可以是一个简单的hashable类型,也可以是一个复杂的unhashable类型,而不需要直接转换为hashable,就像现在的答案所建议的那样。在这种情况下,可能仍然需要一个缓存用于hashable类型(可能更常见)的情况,而不需要使用缓存或在unhashable情况下出错-只需调用底层函数。
这会忽略错误,并且通常适用于任何可散列类型:
字符串
使用和测试:
型
我花了一点时间来理解它,但
example_func.__wrapped__
是lru_cache的版本,example_func.__uncached__
是原始版本。4dc9hkyq4#
您可以将
functools.lru_cache
扩展为摘要列表、字典等。关键思想是将参数的散列值传递给lru_cache
,而不是原始参数。下面是一个示例性的实现,在参数中散列列表和字典。字符串
使用
my_lru_cache
与原始lru_cache
完全相同。型
yvgpqqbh5#
来自@Donatas-Svilpa的答案对我来说很有用,然而,它也需要覆盖关键字参数选项。
字符串
我们可以用这种方式
型
mqxuamgl6#
如果你不需要
LRU
,并且所有的参数都是引用,你可以使用这个简单的实现。字符串