from functools import update_wrapper @update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
wrapper
- функция-обертка,wrapped
- исходная функция,assigned
- какие атрибуты wrapped
присваиваются wrapper
,updated
- какие атрибуты wrapper
обновляются из wrapped
.Декоратор @update_wrapper()
модуля functools
обновляет функцию-обертку wrapped
, чтобы она выглядела как исходная функция wrapper
. Другими словами дополняет функцию-обертку, данными из некоторых атрибутов оборачиваемой функции.
Необязательные аргументы (assigned
и updated
) - это кортежи, указывающие, какие атрибуты исходной функции wrapped
назначаются непосредственно соответствующим атрибутам функции-обертке wrapper
, а какие атрибуты функции-обертки wrapper
обновляются соответствующими атрибутами из исходной функции wrapped
.
Значения по умолчанию для этих аргументов - это константы уровня модуля:
WRAPPER_ASSIGNMENTS
- присваивает функции обертке __module__
, __name__
, __qualname__
, __annotations__
и __doc__
.WRAPPER_UPDATES
- обновляет в функции обертке __dict__
.Чтобы разрешить доступ к исходной функции для самоанализа и других целей, например минуя декоратор кэширования functools.lru_cache()
, @update_wrapper()
автоматически добавляет атрибут __wrapped__
в обертку, которая ссылается на упаковываемую функцию.
Основное предназначение @update_wrapper()
- функции декоратора, которые оборачивают декорированную функцию и возвращают обертку. Если функция декоратора не обновляется, метаданные возвращенной функции будут отражать определение оболочки, а не исходное определение функции, которое обычно менее чем полезно.
Любые атрибуты, указанные в assigned
или updated
, которые отсутствуют в оригинальной функции игнорируются, т. е. декоратор @update_wrapper()
не будет пытаться установить их в функции-обертке. Если в самой функции-обертке отсутствуют какие-либо атрибуты, указанные в updated
, то возникает [исключение AttributeError
][main-exception.
from functools import update_wrapper def my_func(): """Wrapped function.""" return 'This original func' def wrapper_func(): """Wrapper function.""" return 'This wrapper func' >>> wrapper_func = update_wrapper(wrapper_func, my_func) >>> wrapper_func.__name__ # 'my_func' >>> wrapper_func.__doc__ # 'Wrapped function.' >>> wrapper_func() # This wrapper func >>> wrapper_func.__wrapped__() # This original func