python 如何使用装饰器向函数发送参数
How to use a decorator to send arguments to a function in python
我在 python 中有一组函数获取相同的 2 个参数 + 其他参数。
def myMethodA (param1, param2, specificParm)
do code
def myMethodB (param1, param2, specificParm1 specificParam2)
do code
我想创建一个装饰器,通过在调用函数之前推送参数来替换使用前 2 个参数调用的需要:
@withParams()
def myMethodA (specificParam)
do code
但是如果我省略参数那么装饰器也不能调用它,如果我留下它们那么调用者也需要指定它们。
无论如何要解决这个问题?
我可以用 args* 做一些事情但仍然有 specificParam 的命名参数吗?
另外,如何在 myMethodA
中引用 param1 和 param2
作为 kwargs
的一部分,您可以在装饰器的包装函数中调用函数时添加这两个参数。在调用之前,所有装饰函数都会自动将这两个参数作为关键字参数传递:
def withParams(func):
def wrapper(*args, **kwargs):
kwargs['param1'] = 1
kwargs['param2'] = 2
return func(*args, **kwargs)
return wrapper
@withParams
def add(specificparam, *args, **kwargs):
print(specificparam) # 3
print(args) # (4,)
print(kwargs) # {'param2': 2, 'param1': 1}
return specificparam + sum(args) + sum(kwargs.values())
print(add(3,4)) # 10
如果您要从主函数调用传递的只是每个函数的特定参数,则您可以删除 args
部分。
我建议你去老学校,然后使用 functools.partial
:
重新分配名称
# module foo
def func1(common_1, common_2, specific_1):
pass
def func2(common_1, common_2, specific_2, specific_3):
pass
然后在其他地方(或者如果你愿意,可以在文件的下方)你可以这样做:
import functools
import foo
common_args = (1, 'fred')
foo.func1 = functools.partial(foo.func1, *common_args)
foo.func2 = functools.partial(foo.func2, *common_args)
# ...
foo.func1('special')
foo.func2('equally special', 'but different')
听起来您可能想要 functools.partial
。它 returns 一个已经指定了一些参数的新函数:
import functools
def withParams(func):
return functools.partial(func,1,2)
@withParams
def myMethodA (param1, param2, specificParam):
print(param1,param2,specificParam)
@withParams
def myMethodB (param1, param2, specificParam1, specificParam2):
print(param1,param2,specificParam1, specificParam2)
myMethodA(10)
myMethodB(12,13)
1 2 10
1 2 12 13
听起来您需要 functools.partial
来预填充 "constant" 参数:
>>> from functools import partial
>>> def myMethodA(param1, param2, specificParm):
print("myMethodA(", param1, param2, specificParm, ")")
>>>> def myMethodB (param1, param2, specificParm1, specificParam2):
print("myMethodB(", param1, param2, specificParm1, specificParam2, ")")
>>> preMethodA = partial(myMethodA, "p1", "p2")
>>> preMethodB = partial(myMethodB, "p1", "p2")
>>> preMethodA(34)
myMethodA( p1 p2 34 )
>>> preMethodB(8, 9)
myMethodB( p1 p2 8 9 )
我在 python 中有一组函数获取相同的 2 个参数 + 其他参数。
def myMethodA (param1, param2, specificParm)
do code
def myMethodB (param1, param2, specificParm1 specificParam2)
do code
我想创建一个装饰器,通过在调用函数之前推送参数来替换使用前 2 个参数调用的需要:
@withParams()
def myMethodA (specificParam)
do code
但是如果我省略参数那么装饰器也不能调用它,如果我留下它们那么调用者也需要指定它们。
无论如何要解决这个问题? 我可以用 args* 做一些事情但仍然有 specificParam 的命名参数吗? 另外,如何在 myMethodA
中引用 param1 和 param2作为 kwargs
的一部分,您可以在装饰器的包装函数中调用函数时添加这两个参数。在调用之前,所有装饰函数都会自动将这两个参数作为关键字参数传递:
def withParams(func):
def wrapper(*args, **kwargs):
kwargs['param1'] = 1
kwargs['param2'] = 2
return func(*args, **kwargs)
return wrapper
@withParams
def add(specificparam, *args, **kwargs):
print(specificparam) # 3
print(args) # (4,)
print(kwargs) # {'param2': 2, 'param1': 1}
return specificparam + sum(args) + sum(kwargs.values())
print(add(3,4)) # 10
如果您要从主函数调用传递的只是每个函数的特定参数,则您可以删除 args
部分。
我建议你去老学校,然后使用 functools.partial
:
# module foo
def func1(common_1, common_2, specific_1):
pass
def func2(common_1, common_2, specific_2, specific_3):
pass
然后在其他地方(或者如果你愿意,可以在文件的下方)你可以这样做:
import functools
import foo
common_args = (1, 'fred')
foo.func1 = functools.partial(foo.func1, *common_args)
foo.func2 = functools.partial(foo.func2, *common_args)
# ...
foo.func1('special')
foo.func2('equally special', 'but different')
听起来您可能想要 functools.partial
。它 returns 一个已经指定了一些参数的新函数:
import functools
def withParams(func):
return functools.partial(func,1,2)
@withParams
def myMethodA (param1, param2, specificParam):
print(param1,param2,specificParam)
@withParams
def myMethodB (param1, param2, specificParam1, specificParam2):
print(param1,param2,specificParam1, specificParam2)
myMethodA(10)
myMethodB(12,13)
1 2 10 1 2 12 13
听起来您需要 functools.partial
来预填充 "constant" 参数:
>>> from functools import partial
>>> def myMethodA(param1, param2, specificParm):
print("myMethodA(", param1, param2, specificParm, ")")
>>>> def myMethodB (param1, param2, specificParm1, specificParam2):
print("myMethodB(", param1, param2, specificParm1, specificParam2, ")")
>>> preMethodA = partial(myMethodA, "p1", "p2")
>>> preMethodB = partial(myMethodB, "p1", "p2")
>>> preMethodA(34)
myMethodA( p1 p2 34 )
>>> preMethodB(8, 9)
myMethodB( p1 p2 8 9 )