Что такое корутины в Python и как они работают?
Что проверяют
Понимаете ли вы, что корутина это функция, умеющая приостанавливаться, и знаете ли, кто ею управляет.
Как отвечать
Корутина это функция, которая может приостановить себя, отдать управление и позже продолжить с того же места, сохранив локальные переменные. В отличие от обычной функции, у неё не одна точка входа и выхода.
В Python корутина объявляется через async def. Ключевое: вызов такой функции ничего не выполняет, он создаёт объект корутины. Выполнением занимается планировщик, обычно цикл событий asyncio.
await это точка приостановки: корутина говорит «я жду результата, займись другими». Управление возвращается циклу, тот запускает другие готовые задачи, а когда ожидаемое завершается, возобновляет эту корутину.
Всё происходит в одном потоке. Переключение кооперативное, то есть только в точках await, и в этом важное отличие от потоков: между двумя строками без await никто не вклинится, поэтому гонок за данными в привычном виде тут нет.
Полезно различать три сущности: корутина это объект, задача (asyncio.create_task) это корутина, поставленная циклу на выполнение, future это обещание результата.
Механически корутины выросли из генераторов: и там и там есть приостановка с сохранением кадра. Старый синтаксис на генераторах с декоратором был убран в версии 3.11, сейчас только async def.
Ограничения назовите обязательно: выигрыш только на ожидании ввода-вывода, для вычислений это бесполезно; один блокирующий вызов (time.sleep, requests, синхронный драйвер базы) останавливает весь цикл, поэтому нужны асинхронные библиотеки или asyncio.to_thread.
Где спотыкаются
Считают, что корутины работают параллельно на разных ядрах.
Вызывают корутину без await и удивляются, что ничего не произошло.
Ставят блокирующий вызов внутрь корутины.
Не могут объяснить разницу между корутиной и задачей.