Блок 1 — Низкий уровень (3 задачи)
Цель: понять базовую механику wrapper, args, возврат результата.
⸻
Задача 1 — Логирование вызова функции
Создать декоратор:
log_call
Требования:
• перед выполнением функции выводить:
Вызов функции: <имя функции>
• после выполнения выводить:
Функция завершена
Пример использования:
@log_call
def hello():
print("Hello")
hello()
Ожидаемый вывод:
Вызов функции: hello
Hello
Функция завершена
⸻
Задача 2 — Декоратор подсчёта аргументов
Создать декоратор:
count_args
Требования:
• выводить количество переданных аргументов
• работать с любыми функциями
Пример:
@count_args
def add(a, b, c):
return a + b + c
add(1, 2, 3)
Ожидаемый вывод:
Количество аргументов: 3
⸻
Задача 3 — Декоратор изменения результата
Создать декоратор:
double_result
Требования:
• функция возвращает число
• декоратор должен умножить результат на 2
Пример:
@double_result
def get_number():
return 5
print(get_number())
Ожидаемый результат:
10
⸻
Блок 2 — Средний уровень (3 задачи)
Цель: параметры декораторов, работа с результатом, wraps.
⸻
Задача 4 — Повтор функции N раз
Создать декоратор:
repeat(n)
Требования:
• функция должна выполняться n раз
• n передаётся в декоратор
• использовать wraps
Пример:
@repeat(3)
def hello():
print("Hi")
hello()
Ожидаемый вывод:
Hi
Hi
Hi
⸻
Задача 5 — Ограничение минимального времени выполнения
Создать декоратор:
min_time(seconds)
Требования:
• если функция выполняется быстрее — добавить sleep
• итоговое время выполнения ≥ seconds
Пример:
@min_time(2)
def task():
print("Run")
task()
Если функция выполняется за 0.3 сек — добавить задержку 1.7 сек.
⸻
Задача 6 — Кэширование результатов
Создать декоратор:
cache
Требования:
• сохранять результаты функции
• при повторном вызове с теми же аргументами — возвращать из кэша
• вывести:
Из кэша
Пример:
@cache
def square(x):
return x * x
square(4)
square(4)
Ожидаемый вывод:
Из кэша
(при втором вызове)
⸻
Блок 3 — Уровень выше среднего (3 задачи)
Цель: реальные прикладные сценарии.
⸻
Задача 7 — Проверка прав доступа
Создать декоратор:
require_role(role)
Требования:
• функция принимает объект user
• у пользователя есть поле:
user["role"]
• если роль не совпадает — выбросить:
PermissionError
Пример:
@require_role("admin")
def delete_user(user):
print("User deleted")
user = {"role": "admin"}
delete_user(user)
⸻
Задача 8 — Логирование времени выполнения функции
Создать декоратор:
timer
Требования:
• выводить время выполнения функции
• формат:
Функция выполнена за сек
Пример:
@timer
def slow():
import time
time.sleep(1)
slow()
⸻
Задача 9 — Ограничение количества вызовов
Создать декоратор:
limit_calls(max_calls)
Требования:
• функция может быть вызвана ограниченное число раз
• при превышении — выбросить:
RuntimeError
Пример:
@limit_calls(2)
def hello():
print("Hello")
hello()
hello()
hello()
Ожидаемый результат:
RuntimeError
(на третьем вызове)
⸻
Блок 4 — Сложная задача (1 задача)
Цель: комплексная работа с аргументами, временем, состоянием.
⸻
Задача 10 — Retry при ошибках
Создать декоратор:
retry(attempts, delay)
Требования:
• если функция выбрасывает исключение — повторить выполнение
• максимум attempts попыток
• между попытками пауза delay секунд
• если все попытки неудачны — выбросить последнее исключение
Пример:
@retry(attempts=3, delay=1)
def unstable():
import random
if random.randint(0, 1) == 0:
raise ValueError("Ошибка")
print("Успех")
unstable()
Поведение:
• при ошибке повторить
• максимум 3 попытки
• между ними пауза 1 сек
⸻