Ответ
Ключевое различие — в модели выполнения: def создает синхронные функции, а async def — асинхронные корутины (coroutine).
def (Синхронная функция)
- Выполнение: Блокирующее и последовательное. Если функция выполняет долгую операцию (например, сетевой запрос), она блокирует весь поток до своего завершения.
- Вызов: Обычный прямой вызов:
result = my_function().
async def (Асинхронная корутина)
- Выполнение: Неблокирующее. Может приостановить свое выполнение в точке
await, передав управление обратно циклу событий (event loop). Это позволяет выполнять другие задачи, пока корутина ждет завершения долгой I/O-операции (например, ответа от сервера). - Вызов: Требует
awaitвнутри другойasyncфункции:result = await my_coroutine(). Простой вызовmy_coroutine()вернет объект корутины, но не выполнит ее код.
Когда что использовать:
def: Для CPU-bound задач (математические вычисления, обработка данных в памяти) и простого последовательного кода.async def: Для I/O-bound задач (сетевые запросы, работа с файлами, базами данных), где программа большую часть времени ожидает ответа от внешних ресурсов.
Пример:
import asyncio
import time
# Синхронная функция (блокирующая)
def sync_task():
print("Начало синхронной задачи...")
time.sleep(1) # Блокирует поток на 1 секунду
print("...синхронная задача завершена")
return {"data": "sync_data"}
# Асинхронная функция (неблокирующая)
async def async_task():
print("Начало асинхронной задачи...")
await asyncio.sleep(1) # Не блокирует, передает управление
print("...асинхронная задача завершена")
return {"data": "async_data"}
async def main():
# Вызов корутины с помощью await
result = await async_task()
print(result)
# Для запуска асинхронного кода
# asyncio.run(main()) Ответ 18+ 🔞
А, слушай, вот тебе история про двух братьев-близнецов в Python, def и async def. С виду похожи, а по сути — хуй с горы, два разных зверя.
Вот представь, есть у тебя обычный def. Мужик как мужик. Солидный, последовательный. Скажешь ему: «Сходи, принеси пива». Он пошёл, и пока не вернётся с банкой в руках, ты нихуя другого делать не будешь. Стоишь и ждёшь, как лох. Это блокирующее выполнение. Если там, внутри, запрос к базе данных или сайту, который тормозит как черепаха в сиропе, то весь твой поток — в анабиозе, пока операция не завершится. Вызывается просто: result = my_function(). Всё.
А теперь его брат-шизик, async def. Это не функция, а корутина, ёпта. Хитрый такой. Ты ему: «Сходи, принеси пива». Он говорит: «Ага, щас». Дошёл до холодильника, а там дверь не открывается сразу. Вместо того чтобы биться лбом, он говорит: «Окей, я тут на await повисну, пока холодильник не откроется, а ты, event loop, иди другие дела делай!». И управление возвращается циклу событий, который может в это время другую корутину погонять. Холодильник открылся — корутина «просыпается» и таки приносит пиво. Это неблокирующее выполнение. Вызвать его просто так — my_coroutine() — нельзя, получишь просто объект-обещание. Надо сказать await: result = await my_coroutine().
Короче, когда что юзать:
def— когда твоя задача CPU-bound, то есть жрёт процессор: вычисления, сортировки, шифрование. Или когда код простой, линейный, и париться неохота.async def— когда задача I/O-bound, то есть больше ждёт, чем работает: запросы в сеть (API, сайты), чтение/запись файлов, общение с базами данных. Тут асинхронность выжмет все соки из скорости, потому что пока одна корутина ждёт ответа от сервера, другая уже может следующий запрос готовить.
Смотри, как это выглядит в коде, тут всё по-честному:
import asyncio
import time
# Обычный дед-блокировщик
def sync_task():
print("Начало синхронной задачи...")
time.sleep(1) # Всё, пиздец, поток уснул на секунду
print("...синхронная задача завершена")
return {"data": "sync_data"}
# Асинхронный пройдоха
async def async_task():
print("Начало асинхронной задачи...")
await asyncio.sleep(1) # А я, блядь, подожду, но других не буду тормозить!
print("...асинхронная задача завершена")
return {"data": "async_data"}
async def main():
# Работаем с корутиной правильно - через await
result = await async_task()
print(result)
# Чтобы этот цирк запустить, нужен asyncio.run(main())
Вот и вся магия. Выбирай инструмент по задаче, а то получится, как с молотком и микроскопом.