Когда нужно использовать класс, а когда функции в Python
Что проверяют
Умеете ли вы выбирать форму кода по задаче, а не по привычке из Java. В Python модуль уже служит пространством имён, функции это объекты первого класса, и класс нужен не всегда. Следом часто просят привести класс, который лучше переписать функцией, и наоборот.
Как отвечать
Функция подходит, когда код превращает вход в выход и не хранит состояния между вызовами: парсинг, валидация, расчёт, преобразование данных. Такие функции проще тестировать и комбинировать. Немного состояния можно держать в замыкании или зафиксировать аргументы через functools.partial.
Класс оправдан, когда:
- данные и поведение живут вместе: у объекта есть инварианты, которые методы обязаны соблюдать, например баланс счёта не уходит в минус;
- несколько функций таскают одни и те же аргументы: клиент API с базовым адресом, сессией и таймаутами удобнее сделать объектом;
- нужны разные реализации одного контракта: хранилище в памяти и в PostgreSQL за общим
typing.Protocolилиabc.ABC; - есть жизненный цикл ресурса: класс с
__enter__и__exit__, хотя для простых случаев хватит генератора под@contextmanager; - нужны протоколы языка: итерация, сравнение,
__len__, хеширование.
Для чистых контейнеров данных есть @dataclass, NamedTuple и TypedDict, ручной __init__ с присваиваниями писать не нужно.
Полезная эвристика из доклада «Stop Writing Classes»: если у класса два метода и один из них __init__, это функция. Обратный сигнал: функции передают друг другу словарь состояния или меняют глобальную переменную, значит, пора собрать их в объект.
Где спотыкаются
Делают класс только из @staticmethod ради группировки. Для этого в Python есть модуль, а такой класс лишь добавляет лишний уровень при импорте.
Пишут геттеры и сеттеры в стиле Java. Атрибуты в Python открыты, а когда появляется логика доступа, добавляют @property, не меняя интерфейс.
Отвечают про производительность: «классы медленнее». Для проектирования это не аргумент, разница между вызовом метода и функции ничтожна по сравнению с логикой внутри.