簡體   English   中英

Python3 使用 functools.lru_cache 將列表傳遞給 function

[英]Python3 pass lists to function with functools.lru_cache

我想緩存一個將列表作為參數的 function ,但是當我嘗試使用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]))

我想緩存一個將列表作為參數的函數,但是當我嘗試使用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]))

我想緩存一個將列表作為參數的函數,但是當我嘗試使用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]))

我想緩存一個將列表作為參數的函數,但是當我嘗試使用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]))

使用id獲取函數參數的內存地址。

def cacheRef (f):
    cache = {}
    def g (*args):
        cache_key = (seq(args)
                     .map(lambda e: str(id(e)))
                     .make_string('-')
                     )
        if cache_key in cache:
            return cache[cache_key]
        v = f(*args)
        cache[cache_key] = v
        return v
    return g

@cacheRef
def someHeavyWork (p1, p2, p3):
    # some heavy work
    return 'result'

如果某些函數參數應該被視為值,例如str類型,您可以自己完善包裝器。

您可以將functools.lru_cache擴展為摘要列表、字典等。 關鍵思想是將 arguments 的散列值傳遞給lru_cache ,而不是原始的 arguments。 下面是 arguments 中的示例性實現散列列表和字典。

from functools import lru_cache

def hash_list(l: list) -> int:
    __hash = 0
    for i, e in enumerate(l):
        __hash = hash((__hash, i, hash_item(e)))
    return __hash

def hash_dict(d: dict) -> int:
    __hash = 0
    for k, v in d.items():
        __hash = hash((__hash, k, hash_item(v)))
    return __hash

def hash_item(e) -> int:
    if hasattr(e, '__hash__') and callable(e.__hash__):
        try:
            return hash(e)
        except TypeError:
            pass
    if isinstance(e, (list, set, tuple)):
        return hash_list(list(e))
    elif isinstance(e, (dict)):
        return hash_dict(e)
    else:
        raise TypeError(f'unhashable type: {e.__class__}')

def my_lru_cache(*opts, **kwopts):
    def decorator(func):
        def wrapper(*args, **kwargs):
            __hash = hash_item([id(func)] + list(args) + list(kwargs.items()))

            @lru_cache(*opts, **kwopts)
            def cached_func(args_hash):
                return func(*args, **kwargs)
            
            return cached_func(__hash)
        return wrapper
    return decorator

使用my_lru_cache與原始lru_cache

@my_lru_cache(maxsize=None)
def example_func(lst):
    return sum(lst) + max(lst) + min(lst)


print(example_func([1, 2]))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM