Python — единственный язык с идиомами. Это повышает его читабельность и, возможно, его красоту. Декораторы следуют Zen of Python, также известному как «Pythonic».
«Должен быть один — и желательно только один — очевидный способ сделать это.
Хотя поначалу это может быть неочевидно, если только вы не голландец».
Декораторы доступны начиная с Python 2.2. Они были улучшены с помощью PEP318.
Decorators
A decorator(не путать с шаблоном декоратора) — это метод добавления/изменения поведения функций без изменения исходной функции. В Python декоратор — это шаблон проектирования, который позволяет изменять функциональность функции, заключая ее в другую функцию. Внешняя функция называется декоратором, который принимает исходную функцию в качестве аргумента и возвращает измененную версию.
Давайте учиться на примере. Здесь мы объявляем debugдекоратор. Это помогает распечатать вывод функции вместо добавления команд печати, которые впоследствии становятся громоздкими и временами раздражающе утомительными при удалении.
def debug(function):def wrapper(name, address):print (‘Debugging:’)func = function(name, address)print (func)return wrapper@debugdef typical_crunching_function(name, city):return ‘You are ‘+ name + ‘ from ‘+ citytypical_crunching_function(‘John’,’Los Angeles’)
Здесь мы определили декоратор и применили к line 1-6функции синтаксис @.typical_crunching_function line 8
Python Class Decorators
Декораторы классов были представлены в PEP3129. Это произошло после большого сопротивления со стороны сообщества, которое предпочло metaclasses. Основная цель — расширить возможность декорирования функций классами.
Вот пример декоратора класса, улучшающего функциональность функции.
class Accolade:def __init__(self, function):self.function = functiondef __call__ (self, name):# Adding Excellency before namename = «Excellency » + nameself.function(name)# Saluting after the nameprint(«Thanks «+ name+ » for gracing the occasion»)@Accoladedef simple_function(name):print (name)simple_function(‘John McKinsey’)
Здесь Cleanerопределяется класс, который можно использовать для выполнения предварительной и последующей обработки для функции simple_function. В этом примере мы просто добавляем Excellencyв строку nameи после вывода имени благодарим за честь. Этот простой пример демонстрирует, что мы можем использовать декораторы классов для простого выполнения предварительной и последующей обработки аргументов функции. Этими задачами предварительной обработки могут быть любые из перечисленных ниже, не ограничиваясь ими.
- Добавление информации о времени
- Подключение к базам данных
- Закрытие соединений
- Запоминающее хранилище
Некоторые встроенные декораторы классов
Вот некоторые из встроенных декораторов классов.
cache/ memoize
Обратите внимание, что он доступен только в Python >= 3.9. Это позволяет кэшировать предыдущие значения и использовать их повторно вместо пересчета.
from functools import cache@cachedef factorial(n):return n * factorial(n-1) if n else 1print(factorial(10))
property
Этот декоратор позволяет добавлять функции установки и получения к свойству в классе.
class Pencil:def __init__(self, count):self._counter=count@propertydef counter(self):return self._counter@counter.setterdef counter(self, count):self._counter = count@counter.getterdef counter(self):return self._counterHB = Pencil(100)print (HB.counter)HB.counter = 20print (HB.counter)
cached_property
Этот декоратор позволяет кэшировать свойство класса. Это эквивалентно вложению двух декораторов.
@cached@propertydef counter:return self._counter
Выводы
Декораторы — очень удобные и элегантные инструменты, однако они также очень подвержены ошибкам. Поэтому их следует использовать с большой осторожностью.