Хочешь писать лаконичный, читаемый и эффективный код? Тогда декораторы помогут тебе в этом. В седьмой главe "Fluent Python" Лучано Ромальо рассказывает о декораторах и замыкании. Они не очень распространены в Data Science, однако как только вы начинаете проектировать модели и писать ассинхронный код, декораторы становятся бесценными помощниками. Перед тем как мы перейдем к советам, давайте рассмотрим работу декораторов. Декораторы - это простые функции, которые принимают на вход функцию. Чаще всего они изображаются как "@my_decorator"над декорируемой функцией. Однако то, как мы вызываем функцию temperature()может сбить с толку. Нужно просто использоватьdecorator_1(temperature()),как в примере ниже:  Хорошо, значит декораторы - это функции, которые принимают другую функцию в качестве аргументы. Но зачем нам вообще нужно когда-либо их использовать? Декораторы, действительно, универсальные и мощные инструменты. Они широко применяются для асинхронных функций обратного вызова и функционального программирования. Декораторы могут также использоваться для превращения class-like функциональности в непосредственные функции, сокращая при этом время разработки и заполнение памяти. Используйте встроенный декоратор@propertyдля расширения функциональности геттеров и сеттеров. Одним из самых используемых встроенных декораторов является @property. Множетсво ООП языков(Java, С++) предоставляют возможность использовать геттеры и сеттеры. Данные функции используются с целью гарантировать, что наша переменная не вернет/установит некорректное значение.Одним из примеров может служить наша переменная temp, которая по условию должна быть больше нуля. Мы можем расширить функциональность многих вещей, используя @property, делая при этом код чище и динамичнее: Заметьте, что мы удалили все условные операторы из my_setter() для краткости, но смысл остался тот же. Перед тем как мы двинемся дальше, есть еще одно уточнение. В python не существует такого понятия, как "приватные переменные". Префикс "_" указывает на то, что переменная защищена и на нее не стоит ссылаться вне класса. Однако вы все еще можете сделать так: Отсутствие приватных переменных в Python являлось интересной дизайнерской задумкой. Аргументы - это приватные переменные в ООП, которые на самом деле не является таковыми: если кто-то захочет получить к ним доступ, то он может изменить источник кода класса и сделать переменную публичной. Python поощряет "ответственную разработку" и позволяет вам получить извне доступ ко всему в классе. Используйте@classmethodи @staticmethodдля расширения функциональности классов Эти два декоратора многих сбивают с толку, но их отличия налицо:  @classmethod принимает класс в качестве параметра. По этой причине методы классов могут модифицировать сам класс через все его экземпляры.  @staticmethod принимает экземпляр класса. По этой причине статические методы вовсе не могут модифицировать классы. Обратимся к примеру: Самый важный фактор, определяющий значимость методов класса, это их способность служить альтернативным конструктором для наших классов, которые действительно полезны для полиморфизма. Даже если вы не делаете всякие безумные вещи с наследованием, то все еще прекрасно иметь возможность конкретизировать различные версии классов без использования if/else. С другой стороны, статические методы чаще всего используются в качестве вспомогательных функций, которые абсолютно независимы от состояния класса. Заметьте, что функция isAdult(age) не требует привычного self аргумента, так что она не может сослаться на класс, даже если очень захочется. Используйте @functools.wraps, чтобы хранить информацию функции. Запомните, декораторы - это просто функции, которые принимают другие функции. Так что, когда мы вызываем "декорированные" функции, в первую очередь мы вызываем сам декоратор.Этот поток перезаписывает информацию о "декорированной" функции, например, __name__ и __doc__ поля. Чтобы решить эту проблему, мы можем обратиться к следующему декоратору: Без декоратора @wraps результат напечатанного утверждения будет следующим:  Чтобы избежать переписывания важной информации, убедитесь в использовании @functools.wraps   Пишите свои собственные декораторы, чтобы улучшить свой рабочий процесс, но будьте осторожны! Область видимости в декораторах немного странная. У нас нет времени на детали, но есть эта статья. Примите во внимание, что если вы получаете эту ошибку, то вам следует почитать про область видимости декораторов: Перейдем к некоторым пользовательским декораторам. Код ниже добавляет функции в список при вызове Потенциальный пример использования - юнит-тестирование, так же как с pytest. Условно, мы имеем быстрые и медленные тесты. Вместо того, чтобы вручную назначать каждый отдельному списку, мы можем просто добавить@slowили @fastдекораторы для каждой функции, а затем вызвать каждое значение в соответсвующем списке.  Код ниже выводит время исполнения вашей функции Если вы запускаете любой тип запроса данных или обучаете модель с плохими логами, полезно иметь оценку время исполнения программы. Вы можете оценить время исполнения любой функции, пользуясь декоратором @time_it.   Приведенный ниже код выполняет условные проверки параметров функции перед выполнением самой функции.   Этот декоратор применяет логику условий на все параметры x функции. Без декоратора нам бы пришлось писать if is not None  для каждой функции. И это всего лишь несколько примеров. Декораторы действительно могут быть очень полезными! Junior fullstack developer