Reputation: 4092
I have a set of functions in python that gets the same 2 parameters + other parameters.
def myMethodA (param1, param2, specificParm)
do code
def myMethodB (param1, param2, specificParm1 specificParam2)
do code
I waned to create a decorator that replace the need to call with the first 2 parameters by pushing the parameters before calling the function:
@withParams()
def myMethodA (specificParam)
do code
But if I omit the parameters then the decorator can't call it either and if I leave them then the caller need to specify them as well.
anyway to solve this? Can I do something with args* but still have named parameters for specificParam? Also, How can I reference param1 and param2 inside myMethodA
Upvotes: 3
Views: 1417
Reputation: 784
Sounds like you need functools.partial
, to pre-populate the "constant" parameters:
>>> 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 )
Upvotes: 0
Reputation: 177481
It sounds like you may want functools.partial
. It returns a new function with some parameters already specified:
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
Upvotes: 1
Reputation: 15300
I'd recommend you go old school, and just reassign the names using functools.partial
:
# module foo
def func1(common_1, common_2, specific_1):
pass
def func2(common_1, common_2, specific_2, specific_3):
pass
Then elsewhere (or lower in the file, if you like) you can do this:
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')
Upvotes: 0
Reputation: 78546
You can add those two parameters when you call the function in the decorator's wrapper function as part of the kwargs
. All decorated functions will automatically have those two parameters passed as keyword arguments before making the call:
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
You can drop the args
part if all you'll be passing from the main function call are the specific parameters for each function.
Upvotes: 0