Как устроены event loop и GIL, когда брать потоки, процессы или asyncio, что такое дескрипторы и метаклассы, как работают импорт, фикстуры pytest и внедрение зависимостей в FastAPI — то, что спрашивают у разработчика с опытом.
- Чем абстрактный базовый класс (ABC) отличается от Protocol? Middle
ABC — номинальная типизация: класс должен явно наследовать абстрактный класс, а нереализованные @abstractmethod не дадут создать экземпляр. Protocol (3.8) — структурная: подходит…
- Что будет, если внутри async-функции вызвать блокирующий код? Middle
Встанет весь event loop: блокирующий вызов (time.sleep, requests.get, синхронный драйвер БД, тяжёлое вычисление) не отдаёт управление, и все остальные задачи ждут. Решение …
- Как в asyncio работают отмена задач и таймауты? Middle
task.cancel() бросает CancelledError внутрь корутины в точке ближайшего await. Таймаут — asyncio.timeout() (3.11) или wait_for: по истечении задача отменяется, наружу …
- Как устроен event loop в asyncio? Middle
Event loop — цикл в одном потоке: берёт готовые к выполнению задачи, выполняет каждую до ближайшего await, а ожидающие ввода-вывода передаёт ОС (epoll, kqueue) и возвращается к…
- Чем asyncio.gather отличается от TaskGroup и как в них обрабатываются ошибки? Middle
Оба запускают корутины конкурентно. gather при первой ошибке пробрасывает её, но остальные задачи продолжают работать брошенными (если не return_exceptions=True). TaskGroup (3.11)…
- Когда использовать defaultdict, Counter, deque и OrderedDict? Middle
defaultdict(list) — значение по умолчанию для нового ключа (группировка без проверок). Counter — подсчёт: most_common, сложение и вычитание счётчиков. deque — двусторонняя очередь…
- Как пользоваться concurrent.futures и чем ThreadPoolExecutor отличается от ProcessPoolExecutor? Middle
Единый интерфейс пулов: submit возвращает Future, map применяет функцию к итерируемому, as_completed отдаёт результаты по готовности. ThreadPoolExecutor — для ввода-вывода (GIL…
- Чем dataclass отличается от namedtuple и Pydantic-модели? Middle
@dataclass генерирует __init__, __repr__, __eq__ (опционально порядок, хеш, слоты) по аннотированным полям — обычный изменяемый класс без проверки типов. namedtuple — неизменяемый…
- Как написать декоратор с параметрами и зачем нужен functools.wraps? Middle
Декоратор с параметрами — фабрика декораторов: функция принимает параметры и возвращает обычный декоратор, т. е. три уровня вложенности. functools.wraps копирует в обёртку…
- Что такое дескриптор и как на нём построены property и методы? Middle
Дескриптор — объект в атрибуте класса, у которого есть __get__ (и, возможно, __set__, __delete__). При обращении obj.attr Python вызывает эти методы вместо простого чтения. На…
- Как найти и исправить проблему N+1 запросов в Django ORM? Middle
N+1 — один запрос за списком и по запросу на каждый элемент при обращении к связанному объекту в цикле. select_related — JOIN в одном запросе для ForeignKey и OneToOne…
- Как связаны __eq__ и __hash__ и что значит «хешируемый объект»? Middle
Хешируемый объект имеет хеш, неизменный за всё время жизни, и сравнивается через __eq__. Правило: равные объекты обязаны иметь равные хеши. Если класс переопределяет __eq__ без…
- Что такое цепочки исключений (raise from) и как правильно создавать свои исключения? Middle
raise NewError(...) from err сохраняет исходную ошибку в __cause__ — в трассировке «The above exception was the direct cause». Простой raise внутри except ставит __context__…
- Как устроено внедрение зависимостей в FastAPI? Middle
Depends(func) — FastAPI вызывает func перед обработчиком и передаёт результат в параметр. Зависимости образуют граф, результат кэшируется в пределах запроса, зависимость с yield…
- Что меняет сборка Python без GIL (free-threaded)? Senior
Отдельная сборка CPython (python3.13t) без GIL: потоки выполняют Python-код по-настоящему параллельно на разных ядрах. В 3.13 — экспериментальная, в 3.14 — официально…
- Что полезного есть в functools — lru_cache, cache, partial, singledispatch? Middle
lru_cache(maxsize) — мемоизация с вытеснением давно неиспользуемых; cache (3.9) — без ограничения. Аргументы должны быть хешируемыми. partial — зафиксировать часть аргументов…
- Что делают send, throw и yield from у генераторов? Middle
Генератор — не только источник значений: send(x) передаёт значение внутрь (оно становится результатом выражения yield), throw(exc) бросает исключение в точке yield, close()…
- Чем __getattr__ отличается от __getattribute__? Middle
__getattribute__ вызывается при каждом обращении к атрибуту — это сам механизм поиска. __getattr__ вызывается только если атрибут не найден обычным путём. Для прокси, ленивых…
- Как работает импорт модулей и что делать с циклическими импортами? Middle
При первом import модуль ищется по sys.path, выполняется сверху вниз один раз и кладётся в sys.modules; повторные импорты берут его оттуда. Циклический импорт ломается, когда…
- Какие инструменты itertools стоит знать? Middle
Ленивые строительные блоки: chain (склеить), islice (срез итератора), groupby (группы подряд идущих — нужна предварительная сортировка), product/permutations/combinations…
- Почему лямбды, созданные в цикле, возвращают одно и то же значение? Middle
Замыкание захватывает переменную, а не её значение: значение читается в момент вызова. К моменту вызова цикл закончился, и все лямбды видят последнее значение i. Исправление …
- Что такое метакласс и когда он действительно нужен? Senior
Класс — тоже объект, а метакласс — класс класса: он управляет созданием классов. По умолчанию это type. Метакласс нужен редко: регистрация подклассов и проверка их структуры…
- Как работает unittest.mock.patch и почему патчить нужно там, где объект используется? Middle
patch временно заменяет атрибут по имени на Mock. Подменять нужно в модуле, где имя ищется, а не там, где оно определено: если orders.py сделал from payments import charge…
- Какие ограничения есть у multiprocessing и чем fork отличается от spawn? Middle
Процессы не делят память: аргументы и результаты сериализуются pickle и копируются. Лямбды, локальные функции, открытые файлы и соединения не сериализуются. fork копирует процесс…
- Чем __new__ отличается от __init__? Middle
__new__ — статический метод, создаёт и возвращает экземпляр (вызывается первым). __init__ — инициализирует уже созданный объект и ничего не возвращает. __new__ переопределяют…
- Как найти, что тормозит в Python-программе? Middle
Сначала измерить, потом оптимизировать. cProfile (+ snakeviz) — время по функциям локально. py-spy — сэмплирующий профилировщик, подключается к работающему процессу без…
- Как работают фикстуры pytest и что такое их scope? Middle
Фикстура — функция с @pytest.fixture, результат которой pytest передаёт в тест по имени параметра. Код после yield — очистка. scope (function, class, module, package, session)…
- Почему Python медленный и как ускорить вычисления? Middle
CPython — интерпретатор байткода с динамической типизацией: каждая операция проверяет типы, числа — объекты в куче. Ускорение: векторизация (NumPy, pandas — циклы на C)…
- Как Python управляет памятью — подсчёт ссылок и сборщик мусора? Middle
В CPython основной механизм — подсчёт ссылок: у каждого объекта счётчик, и когда он падает до нуля, объект освобождается сразу. Циклические ссылки (a ссылается на b, b на a)…
- Что такое __slots__ и когда его использовать? Middle
__slots__ = ("x", "y") заменяет у экземпляров словарь __dict__ на фиксированные ячейки: объект занимает в несколько раз меньше памяти, доступ к атрибутам чуть быстрее, а добавить…
- Почему a is b для чисел и строк иногда True, а иногда False? Middle
CPython заранее создаёт целые от −5 до 256 и переиспользует их — is для них True. Строки, похожие на идентификаторы, и константы в одном блоке кода интернируются компилятором. Всё…
- Нужны ли блокировки в многопоточном Python-коде, если есть GIL? Middle
Нужны: GIL защищает внутренние структуры интерпретатора, а не ваши инварианты. x += 1 — несколько инструкций байткода (прочитать, сложить, записать), и поток может быть прерван…
- Как в аннотациях Python описать обобщённые типы — TypeVar, Generic, Protocol? Middle
TypeVar — параметр типа: функция first(xs: list[T]) -> T сохраняет связь «что пришло, то и вернулось». Generic — обобщённый класс. С Python 3.12 — новый синтаксис: def…
- Что такое слабые ссылки (weakref) и где они нужны? Middle
Слабая ссылка не увеличивает счётчик ссылок: объект удаляется, когда исчезнут обычные ссылки, а слабая начинает возвращать None. Применение: кэши и реестры, которые не продлевают…
- Чем WSGI отличается от ASGI? Middle
WSGI — синхронный интерфейс между веб-сервером и приложением: один запрос занимает один поток или процесс до ответа (Flask, Django). ASGI — асинхронный: приложение — корутина…