Декораторы Python и сохранение набора параметров декорированной функции (__signature__)
Проблема
Декораторы подменяют исходную функцию.
И при этом изменяет ее “сигнатуру” - набор параметров. У новой функции уже будет тот набор параметров, что в возвращенной декоратором функции, а не тот, что был у исходной.
Порой, это может создать проблемы. Например, если мы далее передаем эту функцию фреймворку swagger transmute, который автоматически строит swagger описание нашего API, анализируя наши обработчики запросов. Этот фреймворк описывает в swagger параметры запросов исходя из параметров наших функций- обработчиков этих запросов.
Но если мы обернули с какой-то целью наш обработчик например в такой декоратор:
то фреймворк уже не увидит исходных параметров.
Он будет видеть только безликие *args, **kwargs
.
И не построит нам корректного swagger-описания.
Как сохранить исходный набор параметров декорированной функции
Как описано в
PEP0362
в Python, начиная с 3.3, можно подменять сигнатуру функции с помощью
атрибута __signature__
:
Как сохранить прочие атрибуты функции после декорирования
Помимо этого, скорее всего мы также захотим сохранить еще ряд атрибутов функции.
Например, __doc__
, что весьма немаловажно, как для автоматического создания
документации, так и для doc-tests - преставьте,
что иначе вы потеряете doc-тесты исходной функции.
Многие атрибуты исходной функции можно сохранить с помощью декоратора
wraps
модуля functools
:
Только __signature__
надо сохранять отдельно.
Это связано с тем что wraps
сохраняеет существующие атрибуты функции, но
атрибута __signature__
скорее всего не будет в вашей исходной функции.
__signature__
не добавляется ко всем функциям автоматически, хотя
и корректно используется, если уже добавлено.
Поэтому этот атрибут и приходится получать с помощью inspect
, а не копированием
из исходной функции с помощью wraps
.