Ответ
Основное отличие заключается в том, что корутина может приостанавливать свое выполнение и передавать управление обратно в цикл событий (event loop), не завершаясь. Обычная функция выполняется от начала до конца без пауз.
Это позволяет корутинам выполнять длительные операции ввода-вывода (I/O) без блокировки всего потока выполнения, что является основой асинхронного программирования.
Сравнительная таблица
| Характеристика | Обычная функция | Корутина (async def) |
|---|---|---|
| Выполнение | Синхронное, блокирующее | Асинхронное, неблокирующее |
| Приостановка | Не может быть приостановлена | Может быть приостановлена с помощью await |
| Возврат значения | Возвращает результат через return |
При вызове возвращает объект корутины, который нужно запустить |
| Основное применение | Вычисления, блокирующие операции | I/O-bound задачи (сетевые запросы, работа с БД) |
Пример
Сравним блокирующую функцию и неблокирующую корутину, которые ждут 1 секунду.
Обычная (блокирующая) функция:
import time
def blocking_task():
print("Blocking task started...")
time.sleep(1) # Блокирует весь поток на 1 секунду
print("Blocking task finished.")
# Вызов
blocking_task()
Корутина (неблокирующая):
import asyncio
async def non_blocking_task():
print("Non-blocking task started...")
# await передает управление event loop, позволяя выполнять другие задачи
await asyncio.sleep(1)
print("Non-blocking task finished.")
# Для запуска корутины нужен event loop
asyncio.run(non_blocking_task())
Ключевое слово await внутри корутины говорит: "эта операция может занять время, я подожду, а ты, event loop, пока займись другими делами".
Ответ 18+ 🔞
Давай разберёмся, в чём тут, блядь, соль, а то народ путается, как слепые котята в помойке. Основная разница между корутиной и обычной функцией — это как между твоей бабушкой, которая вяжет носки до победного конца, и тобой, когда ты обещаешь помыть посуду, но постоянно отвлекаешься на телефон. Корутина может приостановиться на полпути, отдать управление обратно в цикл событий и не сдохнуть при этом. Обычная функция — это солдат, который идёт до конца, пока не получит пулю в лоб или return в лицо.
Это, сука, и есть магия асинхронщины: корутины позволяют ждать ввода-вывода (типа запроса к базе или API), не блокируя весь поток, чтобы остальные задачи не стояли в очереди, как дураки.
Табличка для наглядности, а то мозги заплыли
| Признак | Обычная функция | Корутина (async def) |
|---|---|---|
| Как работает | Синхронно, блокирует всё, пока не кончит | Асинхронно, умеет ждать без блокировки |
| Можно ли приостановить | Ни хуя, только завершить | Да, с помощью await |
| Что возвращает | Результат сразу через return |
Объект-обещание (корутину), который надо запустить |
| Где юзают | Для вычислений, где не надо ждать | Для I/O операций (сеть, файлы, БД) |
Пример, чтобы совсем пиздец стало понятно
Сравним, как обычная функция и корутина ждут одну секунду. Разница — как между стоять в очереди в ЖЭКе и ждать доставку еды дома.
Обычная функция (блокирует всё, как говно в трубе):
import time
def blocking_task():
print("Blocking task started...")
time.sleep(1) # Здесь весь поток встаёт колом на секунду, блядь
print("Blocking task finished.")
# Вызов
blocking_task()
Корутина (неблокирующая, хитрая жопа):
import asyncio
async def non_blocking_task():
print("Non-blocking task started...")
# await говорит: "Я подожду, а ты, event loop, иди другие дела делай"
await asyncio.sleep(1)
print("Non-blocking task finished.")
# Корутину нельзя просто так вызвать, нужен event loop
asyncio.run(non_blocking_task())
Вот и вся магия, ёпта. Ключевое слово await — это как фраза «я отлучился, не худей». Оно передаёт управление обратно в цикл событий, чтобы тот мог пока другие корутины погонять. А обычная функция — это как болт: закрутился и не остановишь, пока не довернёшь до конца.