Decorator (декоратор)
Функция, возвращающая другой объект, поддерживающий вызов.
Обычно используется для трансформации поведения существующей функции (или класса) с использованием синтаксической конструкции
Результатом декорирующей функции должен являться объект, поддерживающий вызов, который и будет связан с именем оригинального, вместо самого оригинального объекта.
Определение функции или класса, может быть задекорировано один или несколько раз. Декораторные выражения вычисляются в ходе обработки объявлений функций/классов в той области видимости, в которой определён декорируемый объект (функция, класс).
Для реализации поддержки передачи в декоратор аргументов требуется немного усложнить конструкцию:
Конструкция
PEP 3129 Декораторы классов в целом аналогичны декораторам функций.
Декораторы классов не так часто используются, как декораторы функций, потому что часто существуют и другие способы решить задачи, которые некоторые пытаются решать при помощи декораторов класса — например, метаклассы или даже обычное наследование. Впрочем, и для них можно отыскать оправданное применение.
@обёртка
(декораторное выражение).Результатом декорирующей функции должен являться объект, поддерживающий вызов, который и будет связан с именем оригинального, вместо самого оригинального объекта.
Определение функции или класса, может быть задекорировано один или несколько раз. Декораторные выражения вычисляются в ходе обработки объявлений функций/классов в той области видимости, в которой определён декорируемый объект (функция, класс).
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 (генератор)
На заметку
Зарегистрированные пользователи могут публиковать свои Статьи.