Возьмём простой декоратор для примера и создадим простую функцию с его использованием:
def decorator_name(f):
def decorated_function(*args, **kwargs):
print("Some code")
return f(*args, **kwargs)
return decorated_function
@decorator_name
def print_hi(name):
print(f'Hi, {name}')
Выведем имя функции:
print(print_hi.__name__)
# --> decorated_function
То есть мы получили название вложенной в декоратор функции, вместо той, о которой хотим получить данные. Но это ещё не всё. Если мы не используем wraps
и пробуем получить строки документации, которые указаны непосредственно в нашей функции, то результат ничего не даст, т.к. будет идти поиск строк документации непосредственно в decorated_function
, и помимо этого в pydoc будет указано, что функция принимает *args, **kwargs
, проще говоря, мы будем получать данные о decorated_function
, а не о нашей функции print_hi
, находящейся под декоратором.
Теперь добавим wraps:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated_function(*args, **kwargs):
print("Some code")
return f(*args, **kwargs)
return decorated_function
@decorator_name
def print_hi(name):
print(f'Hi, {name}')
И повторно выведем имя:
print(print_hi.__name__)
# --> print_hi
Добавим строки документации в функцию print_hi
:
@decorator_name
def print_hi(name):
"""Sample function.
Args:
name: your name.
Returns:
None
"""
print(f'Hi, {name}')
Теперь, если использовать декоратор без wraps
и вызвать __doc__
у функции print_hi
, то мы получим None, т.к. на самом деле мы будем запрашивать строки документации по функции decorated_function
, в которой ранее мы ничего не прописали:
def decorator_name(f):
def decorated_function(*args, **kwargs):
print("Some code")
return f(*args, **kwargs)
return decorated_function
print(print_hi.__doc__)
# -> None
Если мы использовали wraps
, то нам вернутся требуемые строки документации:
def decorator_name(f):
@wraps(f)
def decorated_function(*args, **kwargs):
print("Some code")
return f(*args, **kwargs)
return decorated_function
print(print_hi.__doc__)
"""
-> Sample function.
Args:
name: your name.
Returns:
None
"""
Таким образом functools.wraps
позволяет скопировать данные по типу имени функции, строк документации, списка аргументов и т.п. в информацию о декорируемой функции.