這是一個裝飾者,可以使用像functools.lru_cache
。但是,這是在那個只需要一個參數這是一個平映射與可哈希值並具有固定的64爲您的使用情況maxsize
你將不得不去適應要麼這個例子或您的客戶端代碼的功能針對性。另外,要單獨設置maxsize
,必須實現另一個裝飾器,但由於我不需要它,所以我沒有將頭部纏繞在此處。
from functools import (_CacheInfo, _lru_cache_wrapper, lru_cache,
partial, update_wrapper)
from typing import Any, Callable, Dict, Hashable
def lru_dict_arg_cache(func: Callable) -> Callable:
def unpacking_func(func: Callable, arg: frozenset) -> Any:
return func(dict(arg))
_unpacking_func = partial(unpacking_func, func)
_cached_unpacking_func = \
_lru_cache_wrapper(_unpacking_func, 64, False, _CacheInfo)
def packing_func(arg: Dict[Hashable, Hashable]) -> Any:
return _cached_unpacking_func(frozenset(arg.items()))
update_wrapper(packing_func, func)
packing_func.cache_info = _cached_unpacking_func.cache_info
return packing_func
@lru_dict_arg_cache
def uppercase_keys(arg: dict) -> dict:
""" Yelling keys. """
return {k.upper(): v for k, v in arg.items()}
assert uppercase_keys.__name__ == 'uppercase_keys'
assert uppercase_keys.__doc__ == ' Yelling keys. '
assert uppercase_keys({'ham': 'spam'}) == {'HAM': 'spam'}
assert uppercase_keys({'ham': 'spam'}) == {'HAM': 'spam'}
cache_info = uppercase_keys.cache_info()
assert cache_info.hits == 1
assert cache_info.misses == 1
assert cache_info.maxsize == 64
assert cache_info.currsize == 1
assert uppercase_keys({'foo': 'bar'}) == {'FOO': 'bar'}
assert uppercase_keys({'foo': 'baz'}) == {'FOO': 'baz'}
cache_info = uppercase_keys.cache_info()
assert cache_info.hits == 1
assert cache_info.misses == 3
assert cache_info.currsize == 3
對於一個更通用的方法也可以從第三方庫設置爲key
適當的功能使用裝飾@cachetools.cache。
也許這可以幫助:http://stackoverflow.com/questions/4669391/python-anyone-have-a-memoizing-decorator-that-can-handle-unhashable-論據 – mouad 2011-06-15 13:36:20
我沒有看到這個,但它並沒有真正的幫助。從頭開始寫一個緩存修飾器是不值得在這裏努力,我想堅持標準庫。謝謝你:) – Evpok 2011-06-15 13:40:50
如何子類化'namedtuple'並添加訪問'x [「鍵」]?這可能只是幾行代碼。 – 2011-06-15 13:42:10