Jon*_*eke 3 python caching memoization
我想制作一个记忆功能的python装饰器。例如,如果
@memoization_decorator
def add(a, b, negative=False):
print "Computing"
return (a + b) * (1 if negative is False else -1)
add(1, 2)
add(1, b=2)
add(1, 2, negative=False)
add(1, b=2, negative=False)
add(a=1, b=2, negative=False)
add(a=1, b=2)
Run Code Online (Sandbox Code Playgroud)
我希望输出是
Computing
3
3
3
3
3
3
Run Code Online (Sandbox Code Playgroud)
并且在最后 6 行的任何排列下,输出应该相同。
这相当于找到一个映射,将等效的集合发送*args, **kwargs**
到 memoization 缓存的唯一键dict
。上面的例子*args, **kwargs
等于
(1, 2), {}
(1,), {'b': 2}
(1, 2), {'negative': False}
(1,), {'b': 2, 'negative': False}
(), {'a': 1, 'b': 2, 'negative': False}
(), {'a': 1, 'b': 2}
Run Code Online (Sandbox Code Playgroud)
对于记忆,您可以使用 functools.lru_cache()
.
编辑:这对于您的用例的问题在于,如果它们指定参数的方式不同,它不会认为两个函数调用是相同的。为了解决这个问题,我们可以编写我们自己的装饰器,它位于lru_cache()
并将参数转换为单一规范形式:
from functools import lru_cache, wraps
import inspect
def canonicalize_args(f):
"""Wrapper for functools.lru_cache() to canonicalize default
and keyword arguments so cache hits are maximized."""
@wraps(f)
def wrapper(*args, **kwargs):
sig = inspect.getfullargspec(f.__wrapped__)
# build newargs by filling in defaults, args, kwargs
newargs = [None] * len(sig.args)
newargs[-len(sig.defaults):] = sig.defaults
newargs[:len(args)] = args
for name, value in kwargs.items():
newargs[sig.args.index(name)] = value
return f(*newargs)
return wrapper
@canonicalize_args
@lru_cache()
def add(a, b, negative=False):
print("Computing")
return (a + b) * (1 if negative is False else -1)
Run Code Online (Sandbox Code Playgroud)
Nowadd()
对于问题中的整个调用集只调用一次。每个调用都使用按位置指定的所有三个参数进行。
归档时间: |
|
查看次数: |
816 次 |
最近记录: |