Функция-декоратор, которая кеширует значение декорируемой функции
Есть задание: "Напишите функцию-декоратор, которая сохранит (закеширует) значение декорируемой функции.Если декорируемая функция будет вызвана повторно с теми же параметрами — декоратор должен вернуть сохранённый результат, не выполняя функцию." И подсказка к заданию: "Создайте словарь и при каждом вызове декоратора сохраняйте в нём аргументы задекорированной функции. При каждом вызове проверяйте, не было ли уже аналогичного вызова. Если был — верните результат прошлого вызова, если не было — верните результат декорируемой функции и одновременно сохраните этот результат в словарь. Ключом для каждой записи словаря может быть аргумент декорируемой функции."
Ну и, собственно, уже готовый код задания, в котором мне нужно дописать функцию def cache_args(func):
import time
from functools import wraps
def time_check(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
execution_time = round(time.time() - start_time, 1)
print(f'Время выполнения функции {func.__name__}: {execution_time} с.')
return result
return wrapper
def cache_args(func):
# Здесь код декоратора
...
@time_check
@cache_args
def long_heavy(num):
time.sleep(1)
return num * 2
print(long_heavy(1))
# Время выполнения функции long_heavy: 1.0 с.
# 2
print(long_heavy(1))
# Время выполнения функции long_heavy: 0.0 с.
# 2
print(long_heavy(2))
# Время выполнения функции long_heavy: 1.0 с.
# 4
print(long_heavy(2))
# Время выполнения функции long_heavy: 0.0 с.
# 4
print(long_heavy(2))
# Время выполнения функции long_heavy: 0.0 с.
# 4
Я понимаю, что в данном случае ключ словаря - это аргумент функции: *args. Значение словаря - это значение самой функции. Но как это все написать правильно синтаксически, не знаю.
Ответы (1 шт):
import time
from functools import wraps
def time_check(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
execution_time = round(time.time() - start_time, 1)
print(f'Время выполнения функции {func.__name__}: {execution_time} с.')
return result
return wrapper
def cache_args(func):
dt = {}
@wraps(func)
def wrapper(*args):
if args not in dt: # При каждом вызове проверяйте, не было ли уже аналогичного вызова
dt[args] = func(*args)
return dt[args]
return wrapper
@time_check
@cache_args
def long_heavy(n1, n2):
time.sleep(1)
return n1 + n2
print(long_heavy(1, 2))
print(long_heavy(1, 2))
out:
Время выполнения функции long_heavy: 1.0 с.
3
Время выполнения функции long_heavy: 0.0 с.
3