Python 检查并实时修改来自装饰程序的调用参数
我的用例如下所示:Python 检查并实时修改来自装饰程序的调用参数,python,python-2.7,Python,Python 2.7,我的用例如下所示: @AddOne("b") def func(a, b, c, *args, **kwargs): print a, b, c class AddOne(object): def __init__(self, param_name): self.param_name = param_name def __call__(self, func): @wraps(func) def decorated(*ar
@AddOne("b")
def func(a, b, c, *args, **kwargs):
print a, b, c
class AddOne(object):
def __init__(self, param_name):
self.param_name = param_name
def __call__(self, func):
@wraps(func)
def decorated(*args, **kwargs):
new_args = list(args)
new_kwargs = kwargs
v = extract_parameter_somehow(
func, new_args, kwargs,
self.param_name) + 1
kwargs[self.param_name] = v
return func(*new_args, **kwargs)
return decorated
预期行为:
>>> func(1, 2, 3)
1 3 3
>>> func(a=1, c=3, b=2)
1 3 3
我怀疑我必须在使用inspect
模块时使用getcallargs
或getargspec
之类的东西对decorator进行编码,但我无法以编程方式执行它。我错过什么了吗
编辑:我的尝试如下:
@AddOne("b")
def func(a, b, c, *args, **kwargs):
print a, b, c
class AddOne(object):
def __init__(self, param_name):
self.param_name = param_name
def __call__(self, func):
@wraps(func)
def decorated(*args, **kwargs):
new_args = list(args)
new_kwargs = kwargs
v = extract_parameter_somehow(
func, new_args, kwargs,
self.param_name) + 1
kwargs[self.param_name] = v
return func(*new_args, **kwargs)
return decorated
一个选项(可能有点黑客?)是使用getargspec
,然后对args
和kwargs
# ...
def __call__(self, func):
arg_names = getargspec(func).args
self.param_index = arg_names.index(self.param_name)
@wraps(func)
def decorated(*args, **kwargs):
new_args = list(args)
new_kwargs = kwargs
try:
v = new_args.pop(self.param_index)
except IndexError:
v = new_kwargs.pop(self.param_name)
new_kwargs[self.param_name] = v + 1
return func(*new_args, **new_kwargs)
return decorated
模块
inspect
包含满足要求所需的所有内容:
提供了了解参数及其顺序的准确定义getargspec
处理实际参数并给出它们的值getcallargs
class AddOne(object):
def __init__(self, param_name):
self.param_name = param_name
def __call__(self, func):
self.argspec = inspect.getargspec(func)
@wraps(func)
def decorated(*args, **kwargs):
callargs = inspect.getcallargs(func, *args, **kwargs)
if callargs.has_key(self.param_name):
callargs[self.param_name] += 1
elif callargs[self.argspec.keywords].has_key(self.param_name):
callargs[self.argspec.keywords][self.param_name] += 1
new_args = [ callargs[i] for i in self.argspec.args
] + list(callargs[self.argspec.varargs])
new_kwargs = callargs[self.argspec.keywords]
return func(*new_args, **kwargs)
return decorated
这意味着:
- 使用getcallargs处理作为键控参数给定的默认值和位置参数
- 在位置参数中搜索参数名称-如果找到,增加相应的值
- 如果在位置参数中找不到,请在关键字参数中搜索-如果找到,请增加相应的值
然后,根据
getcallargs
返回值构建位置参数列表和关键字参数的哈希,以允许额外的varargs或其他关键字参数。你的装饰器看起来像什么?@idjaw是的,我刚刚编辑了这篇文章。我意识到我的“正在进行的工作”源代码没有适应以下问题:-/我多任务处理太多了…谢谢!我已经找到了getcallargs
的东西,但是我搞砸了,因为我不理解varargs
和关键字,它们是问题的关键。