сеньорчикОткрыть в Telegram
← блог
7 июля 2026 г.

Вопросы на собеседовании Python: разбор с примерами кода

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

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

Структуры данных: за что их любят на собесе

Самый первый фильтр. Проверяют, понимаете ли вы, чем структуры отличаются по скорости, а не только по синтаксису.

Классика: почему проверка x in s быстрее для множества, чем для списка? Потому что set и dict устроены на хеш-таблице, и поиск по ним в среднем O(1): хеш сразу указывает, где искать. В списке приходится идти подряд, O(n). На миллионе элементов разница между «мгновенно» и «сходи за кофе».

Отсюда тянется вопрос, когда что брать: список для упорядоченной последовательности, множество для проверки принадлежности и убирания дублей, словарь для связи ключ-значение. И маленький трюк, который любят: собрать словарь из списка пар одним выражением.

pairs = [("a", 1), ("b", 2)]
d = {k: v for k, v in pairs}   # dict comprehension

Изменяемое и неизменяемое: главная ловушка

Тема, на которой отсеивают тех, кто учил Python по верхам.

Начинают с простого: чем list отличается от tuple (кортеж неизменяем и может быть ключом словаря), что такое is против == (is сравнивает, один ли это объект в памяти, == смотрит на равенство значений). А дальше достают вот это:

def add(item, target=[]):    # значение по умолчанию создаётся ОДИН раз
    target.append(item)
    return target

add(1)   # [1]
add(2)   # [1, 2], а вовсе не [2]

Список из аргумента по умолчанию создаётся единожды, при определении функции, и живёт между вызовами. Кто попадался, тот запомнил навсегда. Правильно так: target=None, а внутри if target is None: target = []. Этот вопрос обожают, потому что он ловит понимание того, как Python обходится с объектами.

Генераторы и итераторы: про память

Как только речь заходит про большие данные, всплывают генераторы.

Вопрос звучит так: чем генератор лучше списка и когда это важно. Список держит все элементы в памяти сразу. Генератор отдаёт по одному и ничего не хранит, поэтому им можно обрабатывать поток, который в память целиком не влезет.

# перебрать гигабайтный лог, не загружая его в память
lengths = (len(line) for line in open("huge.log"))
total = sum(lengths)

Дальше спросят про yield (превращает функцию в генератор), про разницу между iterable и iterator, и зачем нужен itertools при обработке больших потоков вместо циклов со списками. Ответ один: не материализовать то, что можно обойти лениво.

Функции, замыкания, декораторы

Территория, где junior переходит в уверенного разработчика.

Спросят про *args и **kwargs (произвольные позиционные и именованные аргументы), про замыкания (функция помнит переменные из окружения, где была создана) и про декораторы. Декоратор это функция, которая оборачивает другую функцию, добавляя поведение вокруг неё: логирование, кэш, замер времени, не трогая исходный код. Классическая просьба на собесе: напишите декоратор, который печатает время выполнения функции.

GIL и многопоточность: понимание, а не заклинание

Вопрос с подвохом, на котором видно глубину. Почему в Python потоки не ускоряют тяжёлые вычисления?

Виноват GIL, глобальная блокировка интерпретатора: в каждый момент байткод исполняет только один поток. Поэтому на задачах, упирающихся в процессор, потоки не дают выигрыша, нужен multiprocessing с отдельными процессами. А вот на задачах, где программа ждёт сеть или диск, потоки полезны: пока один ждёт ответа, другой работает. Кандидат, который отвечает «Python однопоточный» или «GIL это просто плохо», не понял сути. Суть в различии между CPU-bound и IO-bound.

Python для анализа данных: pandas и numpy

Если позиция ближе к аналитике или ML, вторая половина будет про эту связку.

Векторизация. Почему операция над всем массивом в numpy или pandas обычно быстрее цикла for по элементам? Потому что цикл крутится в медленном Python, а векторизованная операция уходит в скомпилированный C и работает над всем массивом разом. Первое правило numpy: увидел цикл по строкам датафрейма, подумай, как его убрать.

Broadcasting. Механизм, которым numpy применяет операцию к массивам разной формы, растягивая меньший до большего без физического копирования. Спросят, почему array + 1 прибавляет единицу к каждому элементу.

SettingWithCopyWarning. Боль каждого, кто работал с pandas. Конструкция вроде df[df.a > 0]['b'] = 0 не меняет исходный датафрейм: цепочка индексаций возвращает копию, и присваивание уходит в неё, а не в df. Правильно через .loc: df.loc[df.a > 0, 'b'] = 0. Кто напоролся, тот больше цепочки не пишет.

Как готовиться

Python-собес держится на нескольких десятках повторяющихся сюжетов: мутабельные аргументы, is против ==, генераторы, GIL, векторизация. Прочитать про них мало, ответ должен всплывать сам, потому что на собесе времени думать «а как оно там» не будет.

Ставится это практикой в формате вопрос-ответ-разбор. В Сеньорчике вопросы по Python идут короткими сессиями внутри треков Data Science и аналитики, а движок возвращает темы, где вы плывёте, пока не начнёт отскакивать от зубов. Живые вопросы с разбором собраны в подборке для Data Scientist, а к алгоритмической секции готовит разбор литкода. Начать можно бесплатно.