Возможно, но вы начали неправильно: вам нужно добавить параметр не в декоратор, а в декорированную функцию. В общем случае это довольно сложно, потому что вам придется добавить этот параметр в декорированную функцию и удалить его перед вызовом исходной функции, если только он не существует в исходной функции.
Вот упрощенная версия, которая отображает только состояние read_only и вызывает исходную функцию:
import inspect
from functools import wraps
def transactional_function(func):
sig = inspect.signature(func) # extract the original signature
params = sig.parameters
if 'read_only' in params:
change = False # read_only already exists, just note that
else:
change = True
# let us add a new keyword only parameter 'read_only'
params = list(params.values())
params.append(inspect.Parameter('read_only',
inspect.Parameter.KEYWORD_ONLY))
# re-order the parameter list
params.sort(key=lambda x: {
inspect.Parameter.POSITIONAL_OR_KEYWORD: 0,
inspect.Parameter.POSITIONAL_ONLY: 0,
inspect.Parameter.VAR_POSITIONAL:1,
inspect.Parameter.KEYWORD_ONLY:2,
inspect.Parameter.VAR_KEYWORD:3}[x.kind])
# and set that new parameter list in the signature
sig = sig.replace(parameters = params)
@wraps(func)
def inner(*args, **kwargs):
read_only = kwargs.get('read_only', False)
# remove the parameter if it was added by the decorator
if change and ('read_only' in kwargs):
del kwargs['read_only']
print('read_only', read_only) # add your logic here
return func(*args, **kwargs)
# update the signature of the decorated function
if change:
inner.__signature__ = sig
return inner
Демо-версия:
>>> @transactional_function
def foo(bar):
return bar * 2
>>> foo(2)
read_only False
4
>>> foo(2, read_only=False)
read_only False
4
>>> foo(2, read_only=True)
read_only True
4
и с более сложной подписью:
>>> @transactional_function
def foo2(a, *args, **kwargs):
return a
>>> foo2(2, read_only=True)
read_only True
2