На интервью Python-разработчика в отдел прогнозирования проверяли понимание системных решений и базовых механизмов языка. Кандидат работал с FastAPI и базами данных, но несколько ответов оставались на уровне использования готового API. Ниже — самостоятельный разбор правильных ответов без личных данных участников.
Зачем нужны Kafka и RabbitMQ в микросервисах?
Брокер сообщений отделяет отправителя от обработчика по времени и доступности. Сервис публикует сообщение и не обязан ждать завершения тяжёлой операции. Потребитель заберёт задачу, когда будет готов, а несколько потребителей могут делить очередь.
Это не означает автоматическую гарантию сохранности. Нужно настроить durable-очередь, подтверждения, повторную доставку и идемпотентность. RabbitMQ описывает work queue как способ распределить долгие задачи между фоновыми обработчиками.
Kafka чаще выбирают для потока событий, хранения журнала и повторного чтения по offset. RabbitMQ удобен для очередей задач и сложной маршрутизации. Выбор делают по сценарию, а не по бренду компании.
На уточняющий вопрос сначала назовите желаемое свойство: немедленный ответ, повторная обработка, порядок, масштабирование или независимость сервисов. Затем сравните синхронный вызов и брокер именно по этому свойству. Такой ход показывает инженерный выбор, а не заученную рекомендацию.
Почему список нельзя использовать как ключ dict?
Ключ должен быть хэшируемым: его хэш не меняется, а равенство согласовано с хэшем. Список меняется на месте и поэтому не имеет __hash__. Строки и числа подходят. Кортеж подходит только тогда, когда хэшируем каждый элемент.
Неизменяемость — удобный признак, но точнее говорить именно о протоколе hash/equality. Пользовательский класс тоже может быть ключом, если соблюдает этот контракт. Правила зафиксированы в модели данных Python.
Чем генератор отличается от итератора?
Итератор отдаёт элементы через __next__, а генератор — удобный способ создать итератор с помощью yield или генераторного выражения. Он вычисляет следующее значение по запросу и хранит только состояние выполнения, а не весь результат.
Это полезно для больших файлов и потоков из базы. Но генератор одноразовый: после StopIteration его нельзя перемотать. Если данные нужны повторно, создайте новый генератор или осознанно материализуйте результат в список.
Как yield связан с контекстным менеджером?
Контекстный менеджер выделяет ресурс при входе и гарантированно освобождает его при выходе. В классе это методы __enter__ и __exit__. Декоратор contextlib.contextmanager позволяет записать тот же протокол функцией: код до yield открывает ресурс, блок finally после него закрывает.
В FastAPI зависимость с yield использует похожий жизненный цикл. Сильный ответ связывает код фреймворка с базовым механизмом Python и объясняет, почему очистка сработает даже при исключении.
Декораторы решают другую задачу: добавляют поведение функции. В обёртке используют functools.wraps, чтобы сохранить имя, документацию и другие метаданные исходной функции.
Как реализовать FIFO-очередь в Python?
Для очереди «первым пришёл — первым вышел» используйте collections.deque. append добавляет справа, popleft забирает слева. У списка удаление первого элемента требует сдвинуть остальные ссылки.
from collections import deque
# Очередь хранит задачи в порядке поступления.
tasks = deque(["report", "email"])
tasks.append("backup")
# popleft забирает самую старую задачу без сдвига всего списка.
next_task = tasks.popleft()
print(next_task) # Ожидаемый результат — report.Документация Python прямо указывает на быстрые операции добавления и удаления с обоих концов. Класс-обёртка нужен только если у очереди появляются собственные правила, а не ради самого ООП.
Как устроить связь многие ко многим?
Создайте промежуточную таблицу с внешними ключами на обе сущности. Для students и courses таблица student_courses хранит пары student_id, course_id. Составное ограничение уникальности не даёт записать одну связь дважды.
Индексы выбирают по реальным запросам. В ORM отдельно проверяют N+1: если список студентов вызывает отдельный запрос курсов для каждого, используют подходящую eager loading-стратегию. SQLAlchemy показывает разные варианты загрузки связей и их компромиссы.
Итог: почему кандидат не получил оффер?
Фактический результат исходного материала — оффера не было. Кандидат знал знакомые инструменты, но не смог уверенно объяснить хэшируемость, генераторы, управление ресурсами и эффективную FIFO-структуру. Для роли, связанной с большими объёмами данных, эти пробелы влияли на повседневные решения.
Сильной стороной было умение поддерживать технический диалог и опыт с FastAPI и ORM. После точечной подготовки результат можно заметно улучшить. Мы бы повторили вопросы в тренажёре собеседований ЮНИКОД и отдельно написали минимальные примеры без подсказок.
Источники
частые вопросы
Короткие ответы
Что важнее на Middle Python: фреймворк или база языка?
Нужны оба уровня. Интервьюер часто берёт знакомый приём фреймворка и спрашивает, на каком механизме Python он построен.
Когда REST лучше очереди сообщений?
REST удобен, когда вызывающей стороне нужен немедленный ответ. Очередь подходит для отложенной обработки, буферизации нагрузки и более слабой связи компонентов.
Как готовиться к вопросам на устройство Python?
Напишите минимальный пример, измерьте поведение и объясните ограничение. Для dict, генераторов и deque одной формулировки недостаточно.


