Skip to content

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

100 реальных вопросов с образцовыми ответами и пояснениями для уровня Junior.

Смотреть пример резюме: Python-разработчик

Тренировка флешкарточками

Интервальное повторение · Hunter Pass

Вопросы

python

Списки, кортежи и множества решают разные задачи в зависимости от порядка, изменяемости и уникальности элементов.

  • Список представляет собой упорядоченную изменяемую последовательность.
  • Кортеж упорядочен и неизменяем, поэтому может быть ключом словаря, если его содержимое хешируемо, в отличие от списка.
  • Множество хранит уникальные хешируемые элементы без определённого порядка, автоматически убирает дубликаты и в среднем проверяет принадлежность за O(1).

Зачем это спрашивают: Интервьюер ждёт свойства плюс практические следствия вроде ключей словаря и скорости проверки принадлежности, а не только определения.

immutability

Изменяемость определяет, может ли объект меняться после создания, и влияет на способы его использования.

  • Списки, словари и множества изменяемы, а числа int и float, строки, кортежи и frozenset неизменяемы.
  • Две переменные могут ссылаться на один изменяемый список, поэтому изменение через одно имя будет видно через другое.
  • Неизменяемость делает значение хешируемым и позволяет использовать его как ключ словаря или элемент множества.

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

python

Словарь Python представляет собой хеш-таблицу с быстрым доступом по ключу.

  • Он использует хеш ключа для поиска значения, поэтому поиск, вставка и удаление в среднем работают за O(1).
  • Ключ должен быть хешируемым, например строкой, числом или кортежем неизменяемых значений; список или словарь ключом быть не может.
  • Начиная с Python 3.7 словари сохраняют порядок вставки, но это не заменяет явную сортировку.

Зачем это спрашивают: Требование хешируемости ключей и интуиция про O(1) показывают, понимает ли кандидат структуру глубже синтаксиса.

python

Срез извлекает часть последовательности с помощью записи sequence[start:stop:step].

  • Индекс start включается, stop не включается, а любую часть записи можно опустить.
  • Отрицательные индексы отсчитываются с конца, поэтому items[-3:] возвращает последние три элемента, а items[::-1] переворачивает последовательность.
  • Срез списка создаёт новый список, поэтому items[:] можно использовать как быструю поверхностную копию.

Зачем это спрашивают: Свободное обращение с исключаемой правой границей и отрицательными индексами - быстрый признак повседневной практики в Python.

comprehensions

Списковое включение лучше всего подходит для простого и понятного преобразования или фильтрации с созданием списка.

  • Выражение [x * 2 for x in nums if x > 0] преобразует и фильтрует значения в одной строке.
  • Такой вариант считается питоничным, пока логика преобразования и фильтрации легко читается.
  • Обычный цикл понятнее, если нужны несколько инструкций, побочные эффекты или глубокая вложенность.

Зачем это спрашивают: Интервьюер проверяет и идиоматичный стиль, и здравый смысл отказаться от него, когда страдает читаемость.

pythoncomprehensions

В Python есть словарные и множественные включения, а также ленивые генераторные выражения.

  • Словарное включение может выглядеть как {u.id: u.name for u in users}, а множественное как {x % 10 for x in nums}.
  • Генераторное выражение, например sum(x * x for x in nums), выдаёт значения лениво и не создаёт промежуточный список.
  • Выбор в основном зависит от того, нужен ли весь результат в памяти одновременно.

Зачем это спрашивают: Знание генераторных выражений и причин их экономности отделяет практиков от читателей туториалов.

args-kwargs

Синтаксис *args и **kwargs позволяет функциям принимать или передавать дальше гибкий набор аргументов.

  • *args собирает дополнительные позиционные аргументы в кортеж.
  • **kwargs собирает дополнительные именованные аргументы в словарь.
  • При вызове func(*items, **options) распаковывает последовательность и словарь, что удобно в обёртках и декораторах, передающих аргументы без изменений.

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

Изменяемый аргумент по умолчанию используется совместно разными вызовами и может сохранять неожиданное состояние.

  • В def add_item(item, items=[]) список создаётся один раз при определении функции, а не при каждом вызове.
  • Вызовы без items изменяют один и тот же список, поэтому новый вызов может получить значения, оставшиеся после предыдущего.
  • Следует задать items=None по умолчанию и создать items = [] внутри функции, если items is None.

Зачем это спрашивают: Эта классическая ловушка проверяет, знает ли кандидат, что значения по умолчанию вычисляются один раз при определении.

pythonscope

Python ищет имена по порядку в локальной, объемлющей, глобальной и встроенной областях видимости, то есть по правилу LEGB.

  • Читать переменную из внешней области можно без дополнительного объявления.
  • Присваивание имени внутри функции создаёт локальную переменную, если не указать global или nonlocal.
  • Поэтому изменение глобального списка может работать, а переприсваивание глобального счётчика без global вызывает UnboundLocalError.

Зачем это спрашивают: Правило присваивание-создаёт-локальную и пример с UnboundLocalError выдают настоящее понимание.

python

Python использует передачу через присваивание, то есть функция получает ссылку на тот же объект.

  • Эта модель не является передачей по значению или по ссылке в классическом смысле.
  • Изменение переданного списка внутри функции меняет список вызывающей стороны, потому что обе ссылки ведут на один объект.
  • Перепривязка параметра к новому объекту меняет только локальное имя и не затрагивает вызывающую сторону.

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

python

Операторы == и is сравнивают соответственно равенство значений и идентичность объектов.

  • Оператор == вызывает __eq__ для сравнения значений.
  • Оператор is проверяет, указывают ли два имени на один объект, поэтому два равных списка могут пройти проверку ==, но не is.
  • Сравнение по идентичности уместно для синглтонов, особенно в записи x is None, потому что объект None существует в одном экземпляре.

Зачем это спрашивают: Конвенция x is None - та практическая деталь, которую интервьюеры слушают сверх определения.

copying

Поверхностная и глубокая копии различаются тем, остаются ли вложенные объекты общими с оригиналом.

  • Поверхностная копия создаёт новый внешний контейнер, но сохраняет ссылки на прежние внутренние объекты.
  • Поэтому list(data) и data[:] по-прежнему разделяют вложенные списки, а изменение вложенного словаря может затронуть оригинал.
  • copy.deepcopy рекурсивно копирует содержимое и создаёт полностью независимую структуру.

Зачем это спрашивают: Баг с вложенной структурой показывает, что кандидата это реально кусало.

python

F-строки обычно предпочитают для форматирования, потому что они прямолинейны, читаемы и быстры.

  • Они встраивают выражения напрямую, как в f'{user.name} has {count} items', и поддерживают спецификаторы вроде f'{price:.2f}'.
  • Начиная с Python 3.8 запись f'{value=}' выводит выражение вместе с его значением для быстрой отладки.
  • Процентное форматирование и str.format всё ещё встречаются в старом коде, а в логировании ленивое процентное форматирование используется намеренно.

Зачем это спрашивают: Спецификаторы формата и отладочная форма со знаком = показывают беглость сверх базового синтаксиса.

Многократная склейка строк через + в большом цикле неэффективна, потому что строки неизменяемы.

  • Каждый += создаёт новую строку и копирует всё предыдущее содержимое, из-за чего на больших данных цикл может стать квадратичным.
  • Идиоматичная альтернатива состоит в том, чтобы собрать части в список и один раз вызвать ''.join(parts).
  • Для нескольких склеек разница несущественна, поэтому проблема важна прежде всего в циклах по множеству элементов.

Зачем это спрашивают: Проверяется, связывает ли кандидат неизменяемость с реальным последствием для производительности.

error-handling

Блоки try, except, else и finally разделяют защищаемый код, обработку ошибок, успешное продолжение и очистку ресурсов.

  • Сначала выполняется код в try, а подходящий блок except обрабатывает возникшее исключение.
  • Блок else запускается только при завершении try без исключения и отделяет успешный путь от защищаемого кода.
  • Блок finally выполняется всегда и подходит для очистки, например закрытия ресурсов, которыми не управляет with.

Зачем это спрашивают: Знание, зачем нужен else, отличает тех, кто читал дальше минимального шаблона try/except.

error-handling

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

  • Он ловит KeyboardInterrupt, SystemExit и ошибки вроде NameError, после чего программа может продолжить работу в некорректном состоянии.
  • Следует ловить самое конкретное исключение, которое код способен обработать, например FileNotFoundError или ValueError.
  • Если на верхнем уровне нужен широкий обработчик, стоит ловить Exception, записывать полный трейсбек и затем пробрасывать ошибку дальше или явно завершать работу.

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

error-handling

Исключения должны сообщать о недопустимом вводе или невосстановимом состоянии как можно ближе к причине.

  • Функция может явно отклонить входные данные, например через raise ValueError('amount must be positive').
  • Собственный подкласс Exception, такой как PaymentDeclinedError, позволяет вызывающему коду ловить конкретные отказы, не перехватывая посторонние ValueError.
  • Раннее исключение с понятным сообщением безопаснее возврата None, после которого сбой произойдёт далеко от причины.

Зачем это спрашивают: Раннее поднятие конкретных типов показывает, что кандидат проектирует пути ошибок, а не латает их постфактум.

iterationpythontyping

Протокол итератора даёт Python единый способ обходить списки, файлы, генераторы, словари и другие итерируемые объекты.

  • Итерируемый объект возвращает итератор при вызове iter().
  • Итератор реализует __next__ и выдаёт значения, пока не поднимет StopIteration.
  • Цикл for один раз вызывает iter(), затем многократно вызывает next() и останавливается при StopIteration.

Зачем это спрашивают: Объяснение, во что разворачивается цикл for, доказывает, что концепция понята, а не заучена.

generators

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

  • Генераторная функция использует yield и приостанавливает выполнение между выдаваемыми значениями.
  • Построчная обработка большого лог-файла требует постоянного объёма памяти, тогда как возврат списка загрузил бы весь результат.
  • Генератор можно пройти только один раз, и у него нет len().

Зачем это спрашивают: Аргумент про память плюс ограничение одного прохода - полная картина уровня джуна, которую ждут интервьюеры.

fundamentals

range() возвращает ленивый объект последовательности, а не заранее созданный список.

  • Он вычисляет значения по требованию, поэтому даже range(10**9) почти не занимает памяти.
  • Объект range поддерживает len(), индексацию и быструю проверку принадлежности целых чисел.
  • list(range(n)) нужен только тогда, когда действительно требуется список; в циклах лучше использовать ленивый range напрямую.

Зачем это спрашивают: Маленький вопрос, быстро показывающий, думает ли кандидат о ленивости и памяти.

Закрытые вопросы

  • 21

    Что делают enumerate() и zip() и почему они предпочтительнее арифметики индексов?

    indexes
  • 22

    Какие значения в Python ложные и как это влияет на условия if?

    python
  • 23

    Что такое None и как правильно его проверять?

  • 24

    Как читать и записывать текстовые файлы в Python?

    python
  • 25

    Что такое контекстный менеджер и какую проблему решает оператор with?

    context-managers
  • 26

    Чем sorted() отличается от list.sort() и как работает параметр key?

    sorting
  • 27

    Что такое lambda и когда она уместна?

    lambda
  • 28

    Вы используете map() и filter() или comprehension?

    comprehensions
  • 29

    Что умеет распаковка в Python?

    python
  • 30

    Как Python управляет памятью и сборкой мусора?

    gcmemorypython
  • 31

    Что такое декораторы и как их использовать?

    decorators
  • 32

    Как безопасно прочитать ключ, которого может не быть в словаре?

  • 33

    Чем отличаются list.remove(), list.pop() и del при удалении элементов?

  • 34

    Что происходит при создании экземпляра класса и что такое self?

  • 35

    В чём разница между атрибутами экземпляра и атрибутами класса?

  • 36

    Как работает наследование в Python и что делает super()?

    ooppythonownership
  • 37

    В чём разница между __str__ и __repr__?

    dunder
  • 38

    Что нужно реализовать, чтобы два объекта вашего класса сравнивались как равные по значению?

  • 39

    Что делает декоратор @property?

    decoratorsproperties
  • 40

    В чём разница между @staticmethod и @classmethod?

    oop
  • 41

    Когда вы создаёте класс вместо обычных функций?

  • 42

    Что такое модули и пакеты и что происходит при импорте?

  • 43

    Что делает if __name__ == '__main__' и зачем это нужно?

    modules
  • 44

    Как вы управляете зависимостями проекта через pip?

    dependenciespip
  • 45

    Что такое виртуальное окружение и почему оно нужно каждому проекту?

    venv
  • 46

    Какие инструменты из модуля collections вы находите самыми полезными?

    collections
  • 47

    Как вы работаете с датами и временем в Python?

    python
  • 48

    Как переносимо работать с путями к файлам?

  • 49

    Как сериализовать и парсить JSON в Python?

    serializationpython
  • 50

    Что такое подсказки типов и заставляет ли Python их соблюдать?

    pythontyping
  • 51

    Зачем писать автотесты и что бы вы протестировали первым в небольшом проекте?

    testing
  • 52

    Как pytest находит и запускает тесты?

    pytest
  • 53

    Как вы структурируете отдельный тест, чтобы он оставался читаемым?

  • 54

    Для чего нужны фикстуры pytest?

    pytestfixtures
  • 55

    Как в pytest прогнать один тест на множестве входов?

    pytest
  • 56

    Когда и зачем вы мокаете в тестах?

    mocking
  • 57

    Чем pytest отличается от стандартного модуля unittest?

    pytestunittest
  • 58

    Как вы отлаживаете сбоящий Python-скрипт, кроме добавления принтов?

    python
  • 59

    Как читать трейсбек Python?

    python
  • 60

    В чём разница между TypeError и ValueError и когда появляются KeyError и IndexError?

    indexes
  • 61

    Вы застряли на баге на два часа. Каков ваш процесс?

    problem-solvingconcurrency
  • 62

    Зачем использовать модуль logging вместо print в настоящем коде?

    logging
  • 63

    Опишите ваш базовый рабочий процесс в git при работе над задачей.

    git
  • 64

    Почему команды работают через ветки и пул-реквесты, а не коммитят прямо в главную ветку?

    code-review
  • 65

    Чем git fetch отличается от git pull и что делать с конфликтами слияния?

    git
  • 66

    Что должно лежать в .gitignore Python-проекта?

    gitpython
  • 67

    Как выполнить запрос к базе данных из Python?

    databasequeriespython
  • 68

    Что такое SQL-инъекция и как защититься от неё в Python?

    sqlinjectionpython
  • 69

    Что такое ORM и каковы его плюсы и минусы на вашем уровне?

    orm
  • 70

    Задача требует получить число заказов на пользователя из SQL-базы. Как вы к этому подойдёте?

    sqldatabase
  • 71

    Что такое транзакция базы данных и когда она нужна в коде приложения?

    databasetransactions
  • 72

    С какими основными HTTP-методами и классами статус-кодов вы имеете дело?

    httpstatus-codes
  • 73

    Как вызвать HTTP-API из Python библиотекой requests?

    httppython
  • 74

    API возвращает вложенный JSON-ответ. Как безопасно извлечь из него данные?

    api
  • 75

    Как вы обращаетесь с конфигурацией и секретами вроде API-ключей в Python-проекте?

    soft-skillsapisecrets
  • 76

    Как обработать CSV-файл в Python?

    concurrencypython
  • 77

    Как бы вы посчитали самые частые слова в текстовом файле?

  • 78

    Как обработать файл, который больше вашей оперативной памяти?

    concurrency
  • 79

    Скрипт падает с UnicodeDecodeError при чтении файла. Что происходит и что делать?

  • 80

    Как добавить скрипту аргументы командной строки?

    python
  • 81

    Как должен вести себя консольный скрипт, когда что-то идёт не так?

  • 82

    Внешний API, который зовёт ваш скрипт, отказывает время от времени. Как сделать скрипт устойчивым?

    api
  • 83

    Что значит, что Python - интерпретируемый язык?

    python
  • 84

    Что такое GIL простыми словами и что он значит для вашего кода?

    gil
  • 85

    Что такое PEP 8 и насколько строго вы ему следуете?

    style
  • 86

    На что вы обращаете внимание, когда ревьюят ваш код и когда вы читаете чужой?

  • 87

    Что такое маршрут или эндпоинт в веб-фреймворках вроде Flask или FastAPI?

    frameworksendpoints
  • 88

    Как бы вы выбирали между Django, Flask и FastAPI для нового проекта?

    frameworks
  • 89

    pip install прошёл успешно, но скрипт падает с ModuleNotFoundError. Что проверяете?

    pippackaging
  • 90

    Как вы структурируете небольшой Python-проект?

    python
  • 91

    Как правильно документировать функцию?

  • 92

    Какие сигналы говорят, что функцию пора рефакторить, и как делать это безопасно?

    refactoring
  • 93

    Ваш скрипт работает слишком медленно. Что вы делаете в первую очередь?

  • 94

    Нужно вытащить таймстемп и сообщение об ошибке из каждой строки лог-файла. Как подойдёте?

  • 95

    Вам прилетает тикет с текстом: экспорт сломан, почини. Что вы делаете?

  • 96

    Как вы балансируете между разобраться самому и попросить помощи?

  • 97

    Ваше влитое изменение что-то сломало в продакшене. Что вы делаете?

  • 98

    Как вы продолжаете расти как junior Python-разработчик?

    python
  • 99

    Сеньор на ревью просит изменения, с которыми вы не согласны. Как вы поступаете?

    soft-skillsconflict
  • 100

    Задача занимает намного больше времени, чем вы оценили. Когда и как вы об этом сообщаете?

    communicationestimation