Я собрал серию постов с моей личной базой вопросов для собеседований на Python. Она не идеальна, не полна, и нет, ответов тут нет. Некоторые вопросы могут показаться странноватыми или взятыми из ниоткуда. Но по моему опыту, именно они хорошо показывают, кто на самом деле готов к работе.
Серия разбита на три части по уровню опыта:
- Python Interview Questions for Beginners (Junior)
- Python Interview Questions for Mid-Level Developers
- Python Interview Questions for Experienced Developers (Senior)
Есть вопрос, который, как тебе кажется, должен быть здесь? Или то, что ты сам всегда спрашиваешь на собеседованиях? Дай знать — с удовольствием послушаю!
Что здесь значит «middle»
Для начала определимся с уровнями. Как я это вижу: junior знает синтаксис, middle знает, что ломается в проде, senior знает, что не стоит строить вообще.
У некоторых вопросов ниже есть заметка о том, что я слушаю в ответе. Если ты собеседуешь — вот куда копать. Если готовишься — вот что отличает сильный ответ от заученного, и вот что обычно хочет услышать человек по другую сторону стола.
Вопросы
1. Концепции языка Python
Q: Что выведет -12 % 10?
Q: Что выведет -12 // 10?
Q: Как называется последовательность вычисления операторов в выражении a * b * c?
Q: Почему нельзя использовать изменяемый объект (например, пустой список) в качестве значения по умолчанию для аргумента в Python?
Q: Что делает функция id() в Python?
- Уточнение: Две равные строки могут иметь одинаковый
id(). Почему?
Q: Что такое comprehensions в Python (list, dict, set)? Когда их стоит использовать?
Q: В Python 3.10 добавили structural pattern matching (match/case). Чем это отличается от цепочки if/elif?
- Уточнение: Что
matchможет деструктурировать такого, чтоifне сделает чисто?
Q: Для чего используется ключевое слово yield в Python?
Q: Как отличить итераторы от генераторов в Python?
- Бонус: Напиши пример для каждого.
Q: В чём разница между методами __iter__ и __next__?
Q: Как создать словарь, который сохраняет порядок пар ключ-значение?
Q: Когда стоит использовать dataclass вместо NamedTuple, TypedDict или обычного класса?
Здесь нет неправильного ответа, поэтому его нельзя вызубрить. Я хочу услышать, как изменяемость взвешивается против хешируемости и стоимости в рантайме. И хочу услышать, что TypedDict вообще перестаёт быть классом, как только программа запускается.
- Уточнение: Что даёт
frozen=True, и чего это стоит?
Q: Почему стоит использовать pathlib вместо os.path и конкатенации строк?
Q: Что такое блоки try, except, else и finally? Приведи примеры.
2. Контекстные менеджеры
Q: Что такое контекстный менеджер, и чем он отличается от использования try...finally?
try/finally делает ровно то же самое, поэтому «это более pythonic» — довольно тупой ответ. Я жду __enter__/__exit__ и суть, которая за ними стоит: менеджер можно переиспользовать. С try/finally ты пишешь это заново в каждом месте вызова, пока кто-нибудь однажды не забудет.
Q: Какие методы нужно реализовать, чтобы создать свой класс контекстного менеджера?
Q: Объясни блоки with. Почему они считаются более pythonic, чем try-finally?
Q: Опиши случай, где контекстные менеджеры могут быть полезны.
3. Основы асинхронности
Q: Что такое синхронный код, и чем он отличается от асинхронного кода?
Q: Чем async-функции отличаются от обычных функций Python?
Q: Что такое ключевые слова async и await в Python? Приведи простой пример.
- Уточнение: Что делает
await, и когда его стоит использовать?
Q: Для чего нужен event loop в Python, и как с ним взаимодействует функция asyncio.run()?
Q: Как обрабатывать исключения в асинхронном коде на Python?
Q: Тебе нужно вызвать три независимых async API. Что не так с тем, чтобы ожидать их один за другим, и как бы ты это исправил?
- Уточнение: Один из трёх падает с ошибкой. Что происходит с двумя другими?
Q: Можешь объяснить назначение конструкций async with и async for? Приведи примеры.
Q: Как выполнить файловый ввод-вывод асинхронно в Python?
Q: Когда стоит выбрать асинхронное программирование вместо многопоточности в Python?
4. Продвинутые концепции
Q: Что такое модуль unittest в Python? Как писать тесты на Python?
Q: Современный синтаксис type hints: в чём разница между List[int] и list[int], и между Optional[str] и str | None? Что бы ты написал сегодня?
Ничего сложного здесь нет. Вопрос просто датирует их: ответ показывает, на каком Python они писали последние несколько лет, и насколько они следят за best practices.
Q: Объясни проверку типов в Python. Почему Python считается строго типизированным языком?
- Уточнение: Какие инструменты статического анализа ты бы поставил в CI, и в каком порядке?
Q: Как эффективно изолировать код на Python (например, виртуальные окружения)?
- Уточнение: Что идёт в
pyproject.toml, и что заменило для тебяsetup.py? - Уточнение: В чём разница между lock-файлом и requirements-файлом, и когда эта разница кусается?
Это проверяет разницу между намерением и реализацией. requirements.txt — это то, что выбрал ты сам. Зафиксированные транзитивные зависимости — это то, что выбрал за тебя резолвер. pip freeze > requirements.txt стирает эту границу: он сваливает весь граф в один файл и больше не помнит, какая часть была твоим решением.
Q: Как скопировать объект в Python? В чём разница между поверхностной (shallow) и глубокой (deep) копией?
Перекликается с вопросом про [[]] * 3 чуть ниже. Одно и то же дважды, и мне интересно, свяжут ли они эти два вопроса.
Q: Как в Python управляется память?
- Уточнение: Зачем в Python сборщик мусора, и как он работает?
Q: Как поделиться глобальными переменными между модулями? Это вообще хорошая идея?
Q: Что такое атрибут __slots__ у класса? Какие у него плюсы и минусы?
К этому моменту плюсы, наверное, знают все. Вопрос больше про минусы: нет __dict__, нет атрибутов, которые ты не объявил, и наследование перестаёт быть бесплатным.
Q: Что такое метаклассы в Python?
- Бонус: Как создать класс, не используя оператор class?
5. Задачи на кодинг
Q: Как проверить, что один кортеж содержит все элементы другого кортежа?
Q: Что выведет следующий код?
>>> list = ['a', 'b', 'c', 'd', 'e']
>>> print(list[10:])
Q: Как перезагрузить ранее импортированный модуль? (предположим, что модуль — это файл module.py)
Q: Что выведет следующий код?
>>> a = [[]] * 3
>>> a[1].append(1)
>>> print(a)
Q: Что не так со следующим кодом?
def foo():
from .module import *
print(f"{bar()}")
Q: Файл находится в /usr/lib/python/person.py. Программа запускается командой python /usr/lib/python/person.py. Что будет на выходе?
class Person:
def __init__(self, name):
__name__ = name
def getAge(self):
print(__name__)
p = Person("John")
p.getAge()
Q: Напиши декоратор timeit для измерения времени выполнения функции.
Q: Напиши декоратор, который будет ловить ошибки и повторять функцию максимум 3 раза (настраиваемо).
Q: Что выведет следующий код?
class parent:
def __init__(self, param):
self.v1 = param
class child:
def __init__(self, param):
self.v2 = param
obj = child(11)
print(obj.v1 + " " + obj.v2)
Q: Почини следующий код, чтобы он заработал.
class Repeater:
...
class RepeaterIterator:
...
repeater = Repeater("Hello")
for i in repeater:
print(i) # hello
Q: Напиши код, который получает уникальные значения из списка сложных типов (собственных классов). Пример: [A(1, "ab"), A(2, "ab"), A(2, "aa"), A(1, "ab")] -> [A(1, "ab"), A(2, "ab"), A(2, "aa")].
Q: У нас есть следующий код с неизвестной функцией f(). В f() мы не хотим использовать return, вместо этого мы, возможно, хотим использовать генератор.
for x in f(5):
print(x,)
Вывод выглядит так:
0 1 8 27 64
Напиши функцию f(), чтобы получить вывод выше.
Q: Что выведет следующий код?
x = [[0], [1]]
print(len(' '.join(list(map(str, x)))))
Q: Напиши функцию для генерации всех перестановок строки.
Q: Реализуй базовый LRU (Least Recently Used) кэш.