Декоратор @wraps
Limera1n
К базовой информации о декораторах хочется добавить еще одну важную деталь.
У нас в прошлой статье был декоратор:

Смотрите, а что будет, если я попробую вызвать help в данной функции?

Он нам говорит, что это на самом деле функция wrap, а не функция hello, хотелось вообще то, чтобы выводилось hello. То есть help у нас идет по враперу. Это происходит из-за того, что декоратор нам возвращает врапер. Подобное поведение может принести потенциальные проблемы, например с отладкой приложения, потому что отладка должна понимать, где какие объекты, как они именуются. В процессе отладки можно легко запутаться при таком поведении, запутаемся где какой вызов и куда он идет. Желательно сделать так, чтобы все называлось своими именами. Чтобы добиться такого поведения, мы можем применить декоратор из модуля functools, специальный модуль, который дает возможность использовать специальный декоратор, который называется wraps. И получается, что в результате мы будем использовать декоратор для написания декораторов.
Посмотрим, как его использовать:

Обычно во враперах применяются *args и **kwargs, для того, чтобы можно было передавать любые аргументы и собственно в функцию мы их так же передали.
И этот декоратор wraps работает так, что в результате все метаданные об оборачиваемой функции копируются во внешнюю. И теперь, если мы запросим help(hello), то получаем нормальное имя, видим, что мы работаем то не с декоратором, а с нашей функцией:

Мы же хотим, чтобы при использовании декораторов не наносилось никакого вреда нашему коду, хотелось бы использовать декораторы таким образом, чтобы было ощущение, что мы вроде бы вообще их не используем, и как раз этот магический декоратор wraps дает нам такую возможность.