我正在寻找一些我不确定如何表现并且无法找到答案的东西。
假设我有一个除arg2之外的参数数量未知的函数。此外,arg2没有固定的参数位置:
def some_func(arg1, arg2=None, maybe_arg3=None, maybe_not_arg4=None):
# Do some stuff
现在我想检查用户是否已经传递arg2并将其替换为装饰器,例如:
def some_dec(func):
@wraps(func)
def wrapper(*args, **kwargs):
# Do some stuff
# check if arg2 is passed and replace
rv = func(*args, **kwargs)
return rv
return wrapper
如果它作为键/值传递,那么从kwargs获取它是没有问题但是如果它传递给args我怎么得到它? (因为IDK函数需要的参数数量)
答案 0 :(得分:1)
你可以先查看kwargs
dict的参数,如果缺少,它可能会成为args
中的第二个参数;检查args
是否包含两个以上的参数,并且:
def some_dec(func):
@wraps(func)
def wrapper(*args, **kwargs):
if 'args2' in kwargs:
kwargs['args2'] = 'new value' # update value
elif len(args) > 1:
args = (args[0], 'new value') + args[2:] # rebuild args with new value
rv = func(*args, **kwargs)
return rv
return wrapper
答案 1 :(得分:1)
inspect.signature
应该给你你想要的东西:
def f(x, y, z, a=4):
pass
import inspect
s = inspect.signature(f)
b = s.bind_partial(2, 4, 6, 8)
'a' in b.arguments
-> True
b = s.bind_partial(2, 4, 6)
'a' in b.arguments
-> False
请注意,这是在Python 3.3版本中引入的。在旧版本inspect.getargspec
上提供了一些相同的功能。
所以你的装饰师看起来像:
import inspect
import functools
def nag_a(func):
sig = inspect.signature(func)
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not 'a' in sig.bind_partial(*args, **kwargs).arguments:
print("You really should pass 'a', y'know.")
rv = func(*args, **kwargs)
return rv
return wrapper
def nag_a_27(func):
spec = inspect.getargspec(func)
psn = spec.args.index('a')
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not 'a' in kwargs and len(args) <= psn:
print "You really should pass 'a', y'know."
rv = func(*args, **kwargs)
return rv
return wrapper
@nag_a
def f(x, y, a=None):
pass