这是一个装饰器,可以像
functools.lru_cache
一样使用。但是它针对的是只接受一个参数的函数,该参数是一个具有可哈希值的扁平映射,并且具有固定的
maxsize
,最大为64。针对您的用例,您需要调整此示例或客户端代码。此外,要单独设置
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
如果想要更加通用的方法,可以使用第三方库中的装饰器@cachetools.cache,并将适当的函数设置为key
。
namedtuple
进行子类化并添加通过x ["key"]
访问的功能?这可能只需要几行代码。 - Sven Marnachcollections.namedtuple
,它返回一个type
。因此,如果我想要为命名元组添加__getitem__
,我必须动态地进行操作,这应该是不可能的,即使它是可行的,也非常丑陋。还有其他的方法吗? - Evpoknamedtuple()
返回的类型进行子类化:class X(namedtuple("Y", "a b c")): ...
。 - Sven Marnach