Python3 传递列表以使用 functools.lru_cache 函数

新手上路,请多包涵

我想缓存一个将列表作为参数的函数,但是当我尝试使用 functools.lru_cache 装饰器这样做时,它失败了 TypeError: unhashable type: 'list'


import functools

@functools.lru_cache()
def example_func(lst):
    return sum(lst) + max(lst) + min(lst)

print(example_func([1, 2]))

原文由 redfast00 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

这失败了,因为列表是不可散列的。这将使 Python 很难知道缓存了哪些值。解决此问题的一种方法是在将列表传递给缓存函数之前将列表转换为元组:由于元组不可变且可散列,因此可以缓存它们。

长话短说

使用元组而不是列表:

 >>> @lru_cache(maxsize=2)
... def my_function(args):
...     pass
...
>>> my_function([1,2,3])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    my_function([1,2,3])
TypeError: unhashable type: 'list'

>>> # TO FIX: use a tuple

>>> my_function(tuple([1,2,3]))
>>>

原文由 redfast00 发布,翻译遵循 CC BY-SA 4.0 许可协议

它不应该抛出错误,而是在用户甚至不知道的情况下在装饰器中转换为可哈希的形式。你可以通过像这样装饰你的函数来解决这个问题:

 #Custom Decorator function
def listToTuple(function):
    def wrapper(*args):
        args = [tuple(x) if type(x) == list else x for x in args]
        result = function(*args)
        result = tuple(result) if type(result) == list else result
        return result
    return wrapper

#your cached function
@listToTuple
@lru_cache(maxsize=cacheMaxSize)
def checkIfAdminAcquired(self, adminId) -> list:
    query = "SELECT id FROM public.admins WHERE id IN ({}) and
    confirmed_at IS NOT NULL"
    response = self.handleQuery(query, "int", adminId)
    return response

您可能想在 lru_cache 之后使用另一个装饰器来确保函数的输出不是元组,而是一个列表,因为现在它将返回元组。

原文由 Donatas Svilpa 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题