Декораторы-очень мощный и полезный инструмент в Python, поскольку он позволяет программистам изменять поведение функции или класса. Декораторы позволяют нам обернуть другую функцию, чтобы расширить поведение обернутой функции без ее постоянного изменения.
Примечание: Для получения дополнительной информации обратитесь к декораторам в Python
Как сохранить метаданные?
Это можно сделать с помощью метода wraps() функций. Он обновляет функцию-оболочку, чтобы она выглядела как обернутая функция, копируя такие атрибуты, как __name__, __doc__ (строка документа) и т. д.
Пример:
import time
from functools import wraps
def timethis(func):
'''Decorator that reports the execution time.'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper
@timethis
def countdown(n:int):
'''Counts down'''
while n > 0:
n -= 1
countdown(100000)
print(countdown.__name__)
print(countdown.__doc__)
print(countdown.__annotations__)
Выход:
countdown 0.00827932357788086
countdown
Counts down
{'n': <class 'int'>}
Преимущества использования wraps():
- Копирование метаданных декоратора является важной частью написания декораторов. Если вы забудете использовать @wraps, вы обнаружите, что украшенная функция теряет все виды полезной информации. Например, если этот параметр опущен, вывод последнего примера будет выглядеть следующим образом:
countdown 0.030733823776245117
wrapper
None
{}
- Важной особенностью декоратора @wraps является то, что он делает функцию wrapped доступной для вас в атрибуте __wrapped__. Например, если вы хотите получить прямой доступ к обернутой функции, вы можете сделать это:
countdown.__wrapped__(100000)
- Наличие атрибута __wrapped__ также позволяет оформленным функциям правильно отображать базовую сигнатуру обернутой функции. Например:
from inspect import signature
print(signature(countdown))
Выход:
(n:int)