Співбесіда Python-розробника охоплює внутрішню будову мови, асинхронність, Django або FastAPI і роботу з базою. Нижче — найчастіші питання з еталонними відповідями. Middle: глибше розуміння, оптимізацію та реальні робочі ситуації.
1
У чому різниця між списком і кортежем? Коли обрати кожен?
Відповідь
Списки змінювані, кортежі незмінні, через що кортежі хешовані й годяться як ключі словника. Кортежі трохи швидші й сигналізують читачеві, що це фіксований запис, а не зростаюча послідовність. Список беруть, коли вміст змінюється, кортеж — для фіксованих різнорідних даних на кшталт координат або пари, що повертається.
2
Що таке декоратор? Напишіть декоратор, що вимірює час виконання.
Відповідь
Декоратор — це викликаний обʼєкт, який приймає функцію і повертає заміну, щоб додати поведінку, не чіпаючи вихідне тіло. Декоратор заміру часу загортає виклик: засікти perf_counter до, викликати функцію, засікти після, залогувати різницю й повернути результат. Обовʼязково застосовуйте functools.wraps до внутрішньої функції, щоб імʼя, docstring і сигнатура оригіналу пережили інтроспекцію.
3
Поясніть різницю між генератором і звичайною функцією. Навіщо потрібен yield?
Відповідь
Звичайна функція обчислює все і повертає один раз; генератор призупиняється на кожному yield і відновлюється з того ж місця, віддаючи значення ліниво. Це означає сталу витрату памʼяті незалежно від кількості елементів, тому можна ітеруватися по файлу в гігабайти або по нескінченній послідовності. Саме yield перетворює функцію на скінченний автомат, який інтерпретатор уміє ставити на паузу.
4
Що таке *args і **kwargs? Наведіть приклад використання.
Відповідь
*args збирає зайві позиційні аргументи в кортеж, **kwargs збирає зайві іменовані у словник. Їх застосовують, коли функція має приймати довільну сигнатуру — найчастіше в декораторах і обгортках, що прокидають усе далі. Дзеркальне застосування — розпакування: виклик f(*items, **options) розгортає послідовність і словник в аргументи.
5
У чому різниця між multiprocessing, threading і asyncio?
Відповідь
Threading дає конкурентність усередині одного процесу і допомагає лише на I/O через GIL. Multiprocessing піднімає окремі інтерпретатори зі справжнім паралелізмом ціною запуску процесів і міжпроцесного обміну — це правильний вибір для CPU-навантаження. asyncio це однопотокова кооперативна конкурентність: задачі поступаються керуванням у точках await, що масштабується на десятки тисяч сокетів, але блокує все, якщо всередині корутини викликати синхронний код.
6
Що таке контекстний менеджер? Як реалізувати свій?
Відповідь
Контекстний менеджер гарантує підготовку та завершення навколо блоку — саме це використовує with, щоб закрити файл або відпустити блокування навіть при винятку. Реалізувати можна класом з __enter__ і __exit__ або генератором під декоратором @contextlib.contextmanager, який робить один yield між кодом підготовки та очищення. Метод __exit__ отримує інформацію про виняток і може придушити його, повернувши True.
7
Поясніть MRO і множинне успадкування.
Відповідь
Method Resolution Order задає порядок, у якому Python шукає атрибут по класах, і обчислюється алгоритмом лінеаризації C3. Він гарантує, що клас завжди йде раніше своїх батьків і що порядок базових класів дотримується, завдяки чому ромбоподібне успадкування поводиться передбачувано. super() йде по MRO, а не стрибає одразу до батька, тому кооперативне множинне успадкування вимагає, щоб кожен клас у ланцюжку викликав super().
8
Що таке N+1 у Django ORM? Як допомагають select_related і prefetch_related?
Відповідь
N+1 виникає, коли queryset повертає N обʼєктів, і кожне звернення до повʼязаного поля породжує окремий запит. select_related вирішує це для ForeignKey і OneToOne, роблячи SQL JOIN і заповнюючи повʼязаний обʼєкт тим самим запитом. prefetch_related працює з ManyToMany і зворотними звʼязками: виконує другий запит і зʼєднує результати вже в Python, тому запитів виходить два, а не один.
9
У чому різниця між shallow copy і deep copy?
Відповідь
Поверхнева копія створює новий зовнішній контейнер, але зберігає посилання на ті самі вкладені обʼєкти, тому зміна вкладеного списку видно через обидві копії. Глибока копія рекурсивно дублює все і дає повну незалежність ціною часу й памʼяті. На практиці з цього народжується баг зі змінюваним значенням за замовчуванням або спільним вкладеним конфігом, який один викликач змінює для всіх.
10
У чому різниця між __str__ і __repr__?
Відповідь
__repr__ адресований розробнику і в ідеалі має бути однозначним — часто це вираз, яким обʼєкт можна було б відтворити; саме його показують REPL і відлагоджувачі. __str__ адресований кінцевому користувачу, його викликають print() і str(), а за відсутності він падає назад на __repr__. Звичка реалізовувати __repr__ цінніша, бо вона робить читабельними логи й трейсбеки.
🦎
Прочитати відповіді недостатньо
На співбесіді ти говориш вголос під тиском. Кем поставить ті самі питання, оцінить кожну відповідь і покаже, що саме підтягнути.
Пройти інтерв'ю Middle Python Backend →Безкоштовно · 3 інтерв'ю на місяць