Функция, возвращающая другой объект, поддерживающий вызов.
Обычно используется для трансформации поведения существующей функции (или класса) с использованием синтаксической конструкции @обёртка (декораторное выражение).

Результатом декорирующей функции должен являться объект, поддерживающий вызов, который и будет связан с именем оригинального, вместо самого оригинального объекта.

Определение функции или класса, может быть задекорировано один или несколько раз. Декораторные выражения вычисляются в ходе обработки объявлений функций/классов в той области видимости, в которой определён декорируемый объект (функция, класс).

    from functools import wraps


def add_one_decorator(func):
"""Декоратор. Добавляет единицу к аргументу, передаваемому
в задекорированную функцию.

Аргументы вызова не поддерживаются.

:param function func: Объект функции, задекорированной
данным декоратором.
"""
print('decorator arg: %s' % func)

@wraps(func) # Позволяет актуализировать метаданные функции. См. «На заметку» ниже.
def decoration(arg):
"""Трансформирующая функция, реализующая дополнительную
логику.

:param int arg: Аргумент, который будет передан
в задекорированную функцию.

:rtype: function
"""
print('decorated func arg: %s' % arg)

# Вызываем задекорированную функцию, но к аргументу
# добавляем единицу.
return func(arg + 1)

return decoration


@add_one_decorator
def my_func(arg):
"""Эта функция задекорирована при помощи @add_one_decorator."""
print('my_func: %s' % arg)


my_func(1)
# decorator arg: < function my_func at 0x7f17f0b07d08 >
# decorated func arg: 1
# my_func: 2

На заметку
Модуль functools стандартной библиотеки содержит функцию update_wrapper() и декоратор wraps(), позволяющие актуализировать метаданные (например: имя, модуль, строку документации) декорирующей функции по данным декорируемой. Это удобно, например, для анализа и отладки, в случаях возникновения исключений в задекорированных функциях — без подобной актуализации в трассировочной информации будут отражены данные обёртки из декорирующей функции вместо данных оригинальной функции.

Для реализации поддержки передачи в декоратор аргументов требуется немного усложнить конструкцию:

    def add_some_decorator(decor_arg):
"""Декоратор. Добавляет указанное число к аргументу, передаваемому
в задекорированную функцию.


:param int decor_arg: Аргумент декоратора. Число, которые
требуется прибавить к аргументу задекорированной функции.
"""

def actual_decorator(func):
print('decorator arg: %s' % func)

def decoration(arg):
print('decorated func arg: %s' % arg)

# Вызываем задекорированную функцию, но к аргументу
# добавляем указанное число.
return func(arg + decor_arg)

return decoration

return actual_decorator


@add_some_decorator(3)
def my_func(arg):
print('my_func: %s' % arg)


my_func(1)
# decorator arg: < function my_func at 0x7f17f0b1e268 >
# decorated func arg: 1
# my_func: 4

Конструкция @обёртка — является лишь синтаксическим сахаром и следующие определения примерно эквивалентны с точки зрения смысла («примерно» потому что в первом случае оригинальная функция не будет временно связана с именем func):

@f1(arg)
@f2
def func():
pass

def func():
pass

func = f1(arg)(f2(func))

Декораторы классов


PEP 3129 Декораторы классов в целом аналогичны декораторам функций.

    def add_two_to_attr_class_decorator(decorated_class):
"""Декоратор класса. Прибавляет 2 (два) к атрибуту
декорируемого класса.

"""
decorated_class.attr += 2

return decorated_class


@add_one_to_attr_class_decorator
class MyClass():

attr = 1


MyClass.attr # 3

Декораторы классов не так часто используются, как декораторы функций, потому что часто существуют и другие способы решить задачи, которые некоторые пытаются решать при помощи декораторов класса — например, метаклассы или даже обычное наследование. Впрочем, и для них можно отыскать оправданное применение.
Синонимы поиска: Decorator (декоратор), @
В разделе «def (функция/метод)»: Generator (генератор)
На заметку
Зарегистрированные пользователи могут публиковать свои Статьи.