使用关键字参数 (kwargs) 这很容易,因为 *kwargs 为您提供了装饰器中关键字参数的名称和值。
所以你会收到这样的东西:
func3(1,2,3,4,5,6,7,test="hallo")
会给你:
kwargs{'test': 'hallo'}
所以你可以只搜索“exactly_this_param”并更改它..
但是您选择使用普通参数。这是一步,但也是可能的。
所以这里有一个可能的解决方案:(我用的是python 3)
使用“非关键字参数”(args),您可以使用以下组合:
- args -> 为您提供此 func 调用的实际值的元组
- func.code.co_varnames -> 为您提供函数定义中的参数名称
我将它们分配给变量func_params
func_params = func.__code__.co_varnames
因此您可以在 func.code.co_varnames 中查找 "exactly_this_param" 的索引,并在此更改 args 中的值索引也是如此。这是这个块:
new_args[func_params.index("exactly_this_param")]=999
您还必须将 args 转换为列表 (new_args) 并转换回元组,因为元组在 python 中是不可变的。
这会产生类似这样的结果(示例代码 - 但正在运行):
def decorator(func):
def wrapped(*args, **kwargs):
# a tuple of the names of the parameters that func accepts
print(" ... decorator magic ....")
print(" .... args" + str(args))
print(" .... kwargs" + str(kwargs))
func_params = func.__code__.co_varnames
print(" .... param_names:" + str(func_params))
# grab all of the kwargs that are not accepted by func
new_args=list(args)
new_args[func_params.index("exactly_this_param")]=999
args=tuple(new_args)
print(" .... new_args" + str(args))
return func(*args, **kwargs)
return wrapped
@decorator
def func1(a, b, exactly_this_param, c):
# does something
print("func1 => exactly_this_slightly_different_param: " + str(exactly_this_param))
@decorator
def func2(exactly_this_param):
# does something
print("func2 => exactly_this_slightly_different_param: " + str(exactly_this_param))
@decorator
def func3(a, b, c, d, e, exactly_this_param, *args, **kwargs):
# does something
print("func3 => exactly_this_slightly_different_param: " + str(exactly_this_param))
if __name__ == "__main__":
func1(1,2,3,4)
func2(12)
func3(1,2,3,4,5,6,7,test="hallo")
结果输出显示始终找到该参数并将其更改为 999。
c:\khz\devel>python test_dec.py
... decorator magic ....
.... args(1, 2, 3, 4)
.... kwargs{}
.... param_names:('a', 'b', 'exactly_this_param', 'c')
.... new_args(1, 2, 999, 4)
func1 => exactly_this_slightly_different_param: 999
... decorator magic ....
.... args(12,)
.... kwargs{}
.... param_names:('exactly_this_param',)
.... new_args(999,)
func2 => exactly_this_slightly_different_param: 999
... decorator magic ....
.... args(1, 2, 3, 4, 5, 6, 7)
.... kwargs{'test': 'hallo'}
.... param_names:('a', 'b', 'c', 'd', 'e', 'exactly_this_param', 'args', 'kwargs')
.... new_args(1, 2, 3, 4, 5, 999, 7)
func3 => exactly_this_slightly_different_param: 999
根据this SO question回答。