У разработчиков на Python наблюдается тенденция использовать словари (дикты) там, где нужно, и там, где нет. В основном это касается передачи данных внутри приложения в виде словаря (дикта), вместо создания объекта. Это плохой дизайн, который приводит к целому вороху проблем, самая страшная из которых — такой код невозможно читать.

К примеру, есть код, который вызывает внешнее API и получает в ответ JSON, который уже распарсили в dict. Стоит мне отправлять этот словарь дальше или лучше трансформировать его в экземпляр более специфического класса? Оба варианта возможны. Обычно я предпочитаю использовать классы и объекты, хотя это требует определённых усилий и времени: соответствующий класс надо ещё написать.

Кроме времени и усилий, этот подход немного (или много — всё зависит от задачи и словаря) снизит производительность приложения. Но его преимущества в большинстве случаев перекрывают этот недостаток. Код гораздо легче читать, он получается самодокументированным и поддерживаемым.

Сравните этот пример:

def return_dict():
    response = responses.get("some_api")
    return response.json()

И этот:

class SomeObject:
    @classmethod
    def from_json(cls, json):
        instance = cls()
        # do magic
        return instance

def return_some_object():
    response = responses.get("some_api")
    return SomeObject.from_json(response.json())

Какой пример легче прочитать и понять? Какой будет легче поддерживать?

Я уверен, что через пару месяцев полностью забудется, что возвращает return_dict(). Даже документация не сильно поможет. К тому же валидировать то, что вернула эта функция, очень сложно: обычно функция, валидирующая словарь, выглядит ужасно и представляет собой гигантский if с кучей ветвлений.

С другой стороны, return_some_object() возвращает экземпляр конкретного класса. Если где‑то в коде вы получите такой объект, то гораздо проще понять, что он из себя представляет, какие данные содержит и какие методы предоставляет, чем разгадать структуру словаря. И даже если нет ни строчки документации, разобраться, для чего этот объект нужен, довольно просто. В любом случае гораздо проще работать с экземпляром конкретного класса, а не со словарём.

И последнее: код с классами гораздо проще поддерживать и тестировать. dict — слишком общий класс и не говорит ничего ни о структуре, ни о смысле данных, которые содержит. А если словарь содержит ещё и вложенные словари (это произойдёт практически гарантированно), поддержка кода становится настоящим кошмаром.