python - 确定 *args 是否提供来自装饰器的特定命名参数
问题描述
我有一个装饰器,在那个装饰器中我想检查被装饰的函数是否有一个带有 name 的参数query
。如果它存在,我想像这样检测它的位置*args
:args[1]
。我想在包装函数中执行此操作。我想做这样的事情:
def some_decorator(func):
@wraps(func)
def wrapper_func(*args, **kwargs):
ind = 0
query = ''
for arg in args:
if arg.__name__ == 'query'
query = 'Found'
break
ind +=1
if query == 'Found':
query = args[ind]
return wrapper_func
为了清楚起见,我这样使用它:
@some_decorator
def find_all(self, some_arg, query=None):
pass
问题是,我也将装饰器用于其他功能,具有不同的签名,可能有也可能没有query
参数。我希望这可以澄清事情。
解决方案
如果我对您的理解正确,那么我认为您可以使用该inspect
模块:
import inspect
...
def some_decorator(func):
def wrapper_func(*args, **kwargs):
# get function signature using inspect.signature()
signature = inspect.signature(func)
# find the subset of arguments that are positional-only
positional_args = [name for name in signature.parameters
if signature.parameters[name].kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD)]
# This should give us the names of args that *may* be positional.
# They should also be in the proper order, since positional-or-keyword args
# cannot precede positional-only args.
# Now, we can search for a positional arg named 'query', get an index...
try:
query_idx = positional_args.index('query')
except ValueError:
query_idx = -1
# ... and extract the corresponding value passed for that in *args
if 0 <= query_idx < len(args):
query = args[query_idx]
else:
query = None
# then do something with that
...
return wrapper_func