Sprint 42 — Декораторы (Junior)
Все задачи одного уровня сложности.
⸻
TASK-J1 — Логирование обращений к сервису заказов
Контекст
В компании появилась проблема: менеджеры часто жалуются, что сервис заказов работает медленно, но команда не понимает сколько раз реально вызывается каждый метод.
Требуется добавить логирование через декоратор.
⸻
Данные
orders = {
1001: {"amount": 1200},
1002: {"amount": 500},
1003: {"amount": 3200},
}
Функция:
def get_order(order_id):
return orders.get(order_id)
⸻
Требования
Создать декоратор:
@logger
def get_order(...):
При каждом вызове выводить:
Calling get_order
⸻
Пример
get_order(1001)
get_order(1002)
Результат:
Calling get_order
Calling get_order
⸻
TASK-J2 — Подсчет количества уведомлений
Контекст
Email-сервис рассылает уведомления клиентам.
Руководитель хочет знать сколько уведомлений было отправлено за время работы программы.
⸻
Данные
def send_email(email):
return f"Email sent to {email}"
⸻
Требования
Создать декоратор, который считает количество вызовов функции.
После каждого вызова счетчик должен увеличиваться.
Количество вызовов должно храниться в:
send_email.calls
⸻
Пример
send_email("a@mail.com")
send_email("b@mail.com")
send_email("c@mail.com")
print(send_email.calls)
Результат:
3
Execution time: 2.00 sec
Report ready
⸻
TASK-J3 — Замер времени формирования отчета
Контекст
Каждый вечер система строит отчет по продажам.
Команда хочет понимать сколько времени занимает выполнение функции.
⸻
Данные
import time
def build_report():
time.sleep(2)
return "Report ready"
⸻
Требования
Создать декоратор:
@timer
def build_report():
После выполнения выводить:
Execution time: 2.00 sec
⸻
Ожидаемый результат
build_report()
Execution time: 2.00 sec
Report ready
⸻
Sprint 42 — Декораторы (Middle)
⸻
TASK-M1 — Кеширование профилей клиентов
Контекст
Для каждого клиента строится аналитический профиль.
Построение занимает много времени из-за запросов к БД.
⸻
Данные
customers = {
1: {"name": "Alex"},
2: {"name": "Kate"},
3: {"name": "John"},
}
import time
def get_customer_profile(customer_id):
time.sleep(2)
return customers[customer_id]
⸻
Требования
Реализовать декоратор кеширования.
Если профиль уже был построен для данного клиента — вернуть его из кеша.
⸻
Пример
get_customer_profile(1)
get_customer_profile(1)
Первый вызов:
2 sec
Второй:
[CACHE]
⸻
TASK-M2 — Ограничение количества запросов
Контекст
Некоторые пользователи перегружают API.
Нужно ограничить количество вызовов функции.
⸻
Данные
def create_ticket(user_id):
return "Ticket created"
⸻
Требования
Создать декоратор:
@rate_limit(3)
Пользователь может вызвать функцию не более 3 раз.
На 4-й вызов:
Exception("Limit exceeded")
⸻
Пример
create_ticket(10)
create_ticket(10)
create_ticket(10)
create_ticket(10)
Последний вызов должен завершиться ошибкой.
⸻
TASK-M3 — Проверка авторизации
Контекст
В CRM некоторые операции доступны только авторизованным пользователям.
⸻
Данные
authorized_users = {
1,
2,
5
}
def view_customer(user_id, customer_id):
return customer_id
⸻
Требования
Создать декоратор:
@require_auth
Перед выполнением функции проверить наличие пользователя в списке.
Если пользователя нет:
PermissionError
⸻
Sprint 42 — Декораторы (Senior)
⸻
TASK-S1 — Аудит финансовых операций
Контекст
Все операции списания средств должны попадать в аудит.
⸻
Данные
accounts = {
"A100": 5000,
"A101": 12000
}
def withdraw(account_id, amount):
...
⸻
Требования
Декоратор должен сохранять:
- время вызова
- аргументы
- результат
- исключения
в общий список:
audit_logs = []
⸻
Формат записи
{
"timestamp": "...",
"function": "withdraw",
"args": (...),
"result": ...
}
⸻
TASK-S2 — Регистрация обработчиков событий
Контекст
Платформа обрабатывает десятки событий.
Разработчики хотят автоматически регистрировать обработчики.
⸻
Данные
event_handlers = {}
⸻
Требования
После объявления:
@register("user_created")
def send_welcome_email(event):
...
обработчик автоматически должен попасть в реестр.
⸻
Результат
event_handlers
{
"user_created": send_welcome_email
}
⸻
TASK-S3 — Управление транзакциями
Контекст
При обновлении нескольких таблиц данные должны изменяться атомарно.
Если внутри функции возникает ошибка — изменения отменяются.
⸻
Данные
db = {
"balance": 1000
}
⸻
Функция
def transfer(amount):
db["balance"] -= amount
...
⸻
Требования
Создать декоратор:
@transaction
Логика:
- Сохранить снимок состояния.
- Выполнить функцию.
- Если ошибки нет — сохранить изменения.
- Если ошибка возникла — вернуть состояние к исходному.
⸻
Пример
transfer(100)
Баланс изменился.
transfer(5000)
Возникла ошибка.
Баланс должен остаться прежним.