Python: Объектно-ориентированный дизайн
2026-02-26 19:55 Diff

Fluent Interface или текучий интерфейс — это подход проектирования объектно-ориентированных API. Он симулирует естественный язык, благодаря чему повышает читаемость кода. Этот подход может быть особенно полезным в Python, который известен своей читаемостью и простотой.

В этом уроке мы рассмотрим применение Fluent Interface для повышения читаемости и гибкости кода.

Fluent Interface

Рассмотрим пример обработки коллекций:

Здесь мы строим цепочку вызовов, где каждый метод возвращает объект того же типа, что и первоначальный объект, но в измененной форме. Этот подход позволяет строить цепочки вызовов произвольной длины, что и обозначается термином fluent interface.

Схематически цепочка выглядит так: collection.map(...).reject(...). Это схоже с тем, как работают цепочки вызовов в JavaScript, где такой подход — основной способ строить вычисления на коллекциях.

Fluent Interface упрощает чтение и обработку данных. Для его реализации в Python существуют разные подходы. Начнем с самого простого — использования self.

self

Первый способ создания Fluent Interface основан на возврате self из методов, которые участвуют в построении цепочек. self — ссылка на тот объект, в контексте которого вызывается метод, поэтому его можно возвращать как обычное значение:

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

На практике часто используется другой подход, с которым мы уже познакомились в прошлом курсе. Нужно добавить немного функциональности в ООП — возвращать не self, а создавать новый объект того же типа с обновленной коллекцией:

Теперь каждый вызов возвращает новый объект. Такой код значительно безопаснее в использовании и позволяет без проблем переиспользовать новые коллекции. Изменение одной не приведет к автоматическому изменению всех остальных.

Теперь углубимся и рассмотрим более продвинутый и безопасный способ. Этот метод позволяет создавать новые объекты и сохранять исходные данные без изменений.

self.class

В каждом методе, который участвует в создании текучего интерфейса, последняя строчка всегда содержит один и тот же вызов: Collection(coll). Ее можно записать проще, не дублируя названия класса. Вместо возврата нового экземпляра класса Collection напрямую можно воспользоваться self.

В Python self используется для обозначения текущего экземпляра класса. Когда вызывается self.__class__(coll), создается новый экземпляр текущего класса, что идентично вызову Collection(coll):

Этот прием обеспечивает большую гибкость при наследовании классов, так как self.__class__ всегда ссылается на класс текущего экземпляра, а не на конкретно указанный класс.

Выводы

Применение Fluent Interface может значительно улучшить читаемость и гибкость кода. Однако следует быть осторожным при выборе между изменяемым и неизменяемым вариантами, так как оба подхода имеют свои преимущества и недостатки. Важно выбирать подход в соответствии с требованиями вашего приложения.