Назад к материалам

Видео + статья / Собеседования

Собеседование на Middle Python-разработчика: правильные ответы

Вопросы и правильные ответы для Middle Python: масштабируемый API, кэш, JWT, CPython, dict, потоки, GC, профилирование и декораторы.

Опубликовано
Обновлено
Видео вышло
Видео
31:02
Текст
8 минут

Если ролик не загружается, выберите другую площадку.

Смотреть на

Какие знания проверяли

Собеседование на Middle Python-разработчика началось с опыта, а затем прошло по четырём слоям: веб-архитектура, устройство CPython, производительность и код. Это хороший формат для проверки уровня: кандидат должен не только дать определение, но и выбрать решение под ограничения.

Что значит масштабируемый API и когда нужен кэш

Вопрос: что делает API масштабируемым?

Ответ: способность выдерживать рост нагрузки с предсказуемой задержкой и без ручного изменения каждого узла. Сначала нужны цифры: запросы в секунду, p95 задержки, объём данных и допустимое число ошибок. Затем обсуждают stateless-приложения, горизонтальное масштабирование, базу, очереди и наблюдаемость.

Кэш нужен, когда повторное вычисление или чтение стоит дорого, а данные можно безопасно переиспользовать. Полный ответ включает ключ кэша, TTL, стратегию сброса и поведение при промахе. Руководство MDN отдельно напоминает о private-кэше для персональных ответов.

На интервью стоит привести один сбойный сценарий. Например, после изменения профиля пользователь продолжает видеть старое имя из кэша. Решение зависит от требований: удалить запись при обновлении, сократить TTL или версионировать ключ. Так кандидат показывает, что понимает не только ускорение, но и согласованность данных.

Как работает JWT

Вопрос: как устроена JWT-аутентификация?

После успешного входа сервер выпускает токен с claims и подписью. Клиент отправляет его в следующих запросах, сервер проверяет подпись, срок действия и ожидаемого издателя. Содержимое JWT кодируется, но обычно не шифруется, поэтому секретные данные внутрь не кладут.

JWT подтверждает подлинность набора claims, а права на действие всё равно проверяет приложение. Сильный ответ также затрагивает короткий срок жизни access-токена, защищённое хранение и механизм отзыва или обновления сессии.

Как CPython запускает код и что может быть ключом dict

CPython читает исходник, строит синтаксическое представление, компилирует его в байткод и исполняет инструкции виртуальной машиной. Это объясняет, почему синтаксическая ошибка появляется до выполнения ветки и откуда берутся файлы кэша байткода.

dict использует хэш-таблицу. Ключ должен быть hashable: его хэш не должен меняться, пока ключ находится в словаре, а равные объекты обязаны иметь одинаковый хэш. Поэтому строки и кортежи из неизменяемых элементов подходят, а обычные списки — нет.

Потоки, процессы и сборщик мусора

Потоки разделяют память процесса и удобны для I/O: пока один поток ждёт сеть, другой может работать. Для тяжёлых вычислений Python-кода GIL в обычной сборке CPython ограничивает параллельное исполнение байткода, поэтому чаще используют процессы.

Основная часть объектов освобождается подсчётом ссылок. Циклический GC находит группы объектов, которые ссылаются друг на друга, но больше недоступны программе. Ответ «GC удаляет всё ненужное» слишком общий: на Middle-уровне нужно различать эти два механизма.

Как искать узкое место

Вопрос: программа работает медленно — что делать?

Сначала воспроизвести проблему и измерить её. Для CPU подойдут cProfile и профилировщики строк, для памяти — снимки распределений, для веб-сервиса — трассировка запросов и метрики базы. После изменения повторяют тот же замер.

Сложность алгоритма тоже оценивают в контексте. O(n²) — предупреждение при росте входа, но не доказательство реальной проблемы на маленьком списке. И наоборот, один сетевой запрос внутри линейного цикла способен доминировать над вычислениями. Сначала находим дорогую операцию, затем оцениваем, как часто она выполняется и можно ли уменьшить число вызовов.

Симптом Первый вопрос
Высокий CPU Какая функция забирает время?
Долгое ожидание Сеть, диск, блокировка или база?
Растёт память Какие объекты удерживаются и кем?
Медленный API На каком участке выросла p95 задержка?

Как написать декоратор для sync и async

В практической задаче требовалось сохранить один интерфейс для обычной и асинхронной функции. Нельзя вызывать корутину как обычный результат: для неё нужен await. Поэтому тип функции определяем один раз при декорировании и возвращаем подходящую обёртку.

Пример кодаPython
import functools
import inspect


def trace_call(func):
    # Для async def возвращаем асинхронную обёртку с await.
    if inspect.iscoroutinefunction(func):
        @functools.wraps(func)
        async def async_wrapper(*args, **kwargs):
            # Ждём результат корутины, а не возвращаем её объект наружу.
            result = await func(*args, **kwargs)
            print(f"{func.__name__} завершена")
            return result

        return async_wrapper

    # Для обычной функции await не нужен.
    @functools.wraps(func)
    def sync_wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        print(f"{func.__name__} завершена")
        return result

    return sync_wrapper

Почему кандидат не получил оффер

Теоретическая база была неровной, но главным сигналом стала практическая часть. Кандидат не собрал корректную схему для sync- и async-функций и долго двигался без уточнения контракта. Для Middle-позиции от него ждали более уверенного обращения с базовыми механизмами языка.

  • Могу объяснить механизм, а не только термин.
  • Перед кодом уточняю вход, выход и крайние случаи.
  • Различаю I/O- и CPU-нагрузку.
  • После оптимизации повторяю исходный замер.
  • Проверяю решение на обычном и асинхронном сценарии.

Источники

частые вопросы

Короткие ответы

Что должен знать Middle Python-разработчик про CPython?

Нужно понимать путь от исходного кода к байткоду, роль интерпретатора, подсчёт ссылок и циклический сборщик мусора. Глубину ответа уточняют по задаче.

Когда потоки ускоряют Python-программу?

Чаще всего при ожидании сети, диска и других I/O-операций. Для вычислительной нагрузки в CPython обычно рассматривают процессы, векторизацию или нативный код.

Как готовиться к практической части?

Сначала проговорите контракт функции и крайние случаи, затем напишите простую рабочую версию и только после этого улучшайте её.

следующий шаг

Отработайте ответы до реального собеседования

Тренажёр ЮНИКОД помогает повторить теорию, найти пробелы и научиться отвечать коротко, точно и по существу.

Перейти в тренажёр →