@lru_cache
не идеален со значениями функций по умолчанию
мой mem
декоратор:
import inspect
def get_default_args(f):
signature = inspect.signature(f)
return {
k: v.default
for k, v in signature.parameters.items()
if v.default is not inspect.Parameter.empty
}
def full_kwargs(f, kwargs):
res = dict(get_default_args(f))
res.update(kwargs)
return res
def mem(func):
cache = dict()
def wrapper(*args, **kwargs):
kwargs = full_kwargs(func, kwargs)
key = list(args)
key.extend(kwargs.values())
key = hash(tuple(key))
if key in cache:
return cache[key]
else:
res = func(*args, **kwargs)
cache[key] = res
return res
return wrapper
и код для тестирования:
from time import sleep
@mem
def count(a, *x, z=10):
sleep(2)
x = list(x)
x.append(z)
x.append(a)
return sum(x)
def main():
print(count(1,2,3,4,5))
print(count(1,2,3,4,5))
print(count(1,2,3,4,5, z=6))
print(count(1,2,3,4,5, z=6))
print(count(1))
print(count(1, z=10))
if __name__ == '__main__':
main()
результат - только 3 раза со сном
но с @lru_cache
этим будет 4 раза, потому что это:
print(count(1))
print(count(1, z=10))
будет рассчитан дважды (плохо работает со значениями по умолчанию)