• Зачем нужен декоратор @dp и все в этом духе, типо @dp.message_handler() в aiogram?

    Vindicar
    @Vindicar
    RTFM!
    На пальцах: чтобы бот работал, его функции должны вызываться при наступлении определённых событий (например, входящего сообщения). Проблема в том, что aiogram знает о возможных событиях, но ему нужно сказать, какие функции когда вызывать. Обычно это называется "зарегистрировать обработчик".
    В питоне функции - объекты первого рода, т.е. их можно сохранять в переменные, передавать как параметры, возвращать как результат и вообще поступать с ними как с любым другим значением.
    Т.е. по идее можно было бы сделать так:
    async def echo(message: Message):
        text = f"Привет, ты написал {message.text}"
        await bot.send_message(chat_id=message.from_user.id, text=text)
    
    dp.register_function_for_message(echo)  # это не настоящий метод aiogram, только пример

    Тогда каждому объявленному обработчику событий соответствовал бы вызов метода, ответственного за регистрацию этого обработчика.

    Но то же самое можно сделать через декораторы. Декоратор - это сокращённый вызов функции, которая принимает в качестве параметра другую функцию.
    Т.е. вот это
    @dp.message_handler()
    async def echo(message: Message):
        text = f"Привет, ты написал {message.text}"
        await bot.send_message(chat_id=message.from_user.id, text=text)

    абсолютно эквивалентно вот этому
    _decorator = dp.message_handler()
    
    async def echo(message: Message):
        text = f"Привет, ты написал {message.text}"
        await bot.send_message(chat_id=message.from_user.id, text=text)
    
    echo = _decorator(echo)

    Как видишь, очень похоже на "простую" регистрацию обработчика, но записывается чуть короче.
    Ответ написан