Python 装饰器 returns 替换一个或多个参数的函数
Python decorator that returns a function with one or more arguments replaced
我想为一组函数创建装饰器,以替换函数的一个或多个参数。我想到的第一个想法是创建一个装饰器,该装饰器 returns 带有替换参数的函数的一部分。
我对装饰函数的调用方式不满意,但即使在调用它时 "properly",我也会收到 TypeError。
下面是一些示例代码:
def decor(func, *args, **kwargs):
def _new_func(*args, **kwargs):
return partial(func, *args, **kwargs, v=100)
return _new_func
@decor
def some_function(a, v, c):
return a, v, c
some_function(1,2,3) # functools.partial(<function some_function at 0x7f89a8bed8c8>, 1, 2, 3, v=100)
some_function(1,2,3)(1,2,3) # TypeError: some_function() got multiple values for argument 'v'
我确信有一种简单的方法可以创建一个装饰器来替换一些参数,但还没有弄清楚。
你必须return部分作为装饰结果:
def decor(func):
return partial(func, v=100)
但是,即使您按位置为 v
传入另一个值,此 始终 设置 v=100
。你仍然会遇到同样的问题。
您需要创建一个知道位置参数 v
是什么的装饰器,并在那里寻找 和 作为关键字参数:
from inspect import getargspec
def decor(func):
vpos = getargspec(func).args.index('v')
def wrapper(*args, **kwargs):
if len(args) > vpos:
args = list(args)
args[vpos] = 100
else:
kwargs['v'] = 100
return func(*args, **kwargs)
return wrapper
上面的装饰器会将 v
参数设置为 100,always。无论您尝试将 v
设置为位置参数还是关键字参数,最终它都会被设置为 100:
>>> @decor
... def some_function(a, v, c):
... return a, v, c
...
>>> some_function(1, 2, 3)
(1, 100, 3)
>>> some_function(1, v=2, c=3)
(1, 100, 3)
如果您只想为 v
提供默认参数(如果未明确设置),则必须反转测试:
def decor(func):
vpos = getargspec(func).args.index('v')
def wrapper(*args, **kwargs):
if len(args) <= vpos and 'v' not in kwargs:
kwargs['v'] = 100
return func(*args, **kwargs)
return wrapper
此时 v
仅在尚未设置的情况下提供:
>>> @decor
... def some_function(a, v, c):
... return a, v, c
...
>>> some_function(1, c=3) # v not set
(1, 100, 3)
>>> some_function(1, 2, c=3) # v is set
(1, 2, 3)
>>> some_function(1, v=2, c=3) # v is set as keyword argument
(1, 2, 3)
我想为一组函数创建装饰器,以替换函数的一个或多个参数。我想到的第一个想法是创建一个装饰器,该装饰器 returns 带有替换参数的函数的一部分。 我对装饰函数的调用方式不满意,但即使在调用它时 "properly",我也会收到 TypeError。
下面是一些示例代码:
def decor(func, *args, **kwargs):
def _new_func(*args, **kwargs):
return partial(func, *args, **kwargs, v=100)
return _new_func
@decor
def some_function(a, v, c):
return a, v, c
some_function(1,2,3) # functools.partial(<function some_function at 0x7f89a8bed8c8>, 1, 2, 3, v=100)
some_function(1,2,3)(1,2,3) # TypeError: some_function() got multiple values for argument 'v'
我确信有一种简单的方法可以创建一个装饰器来替换一些参数,但还没有弄清楚。
你必须return部分作为装饰结果:
def decor(func):
return partial(func, v=100)
但是,即使您按位置为 v
传入另一个值,此 始终 设置 v=100
。你仍然会遇到同样的问题。
您需要创建一个知道位置参数 v
是什么的装饰器,并在那里寻找 和 作为关键字参数:
from inspect import getargspec
def decor(func):
vpos = getargspec(func).args.index('v')
def wrapper(*args, **kwargs):
if len(args) > vpos:
args = list(args)
args[vpos] = 100
else:
kwargs['v'] = 100
return func(*args, **kwargs)
return wrapper
上面的装饰器会将 v
参数设置为 100,always。无论您尝试将 v
设置为位置参数还是关键字参数,最终它都会被设置为 100:
>>> @decor
... def some_function(a, v, c):
... return a, v, c
...
>>> some_function(1, 2, 3)
(1, 100, 3)
>>> some_function(1, v=2, c=3)
(1, 100, 3)
如果您只想为 v
提供默认参数(如果未明确设置),则必须反转测试:
def decor(func):
vpos = getargspec(func).args.index('v')
def wrapper(*args, **kwargs):
if len(args) <= vpos and 'v' not in kwargs:
kwargs['v'] = 100
return func(*args, **kwargs)
return wrapper
此时 v
仅在尚未设置的情况下提供:
>>> @decor
... def some_function(a, v, c):
... return a, v, c
...
>>> some_function(1, c=3) # v not set
(1, 100, 3)
>>> some_function(1, 2, c=3) # v is set
(1, 2, 3)
>>> some_function(1, v=2, c=3) # v is set as keyword argument
(1, 2, 3)