My task is passing a variable with a values in decorator which would replace the variable to it value as key in dictionary, something like this:
@parameters(param1 = parameter1)
x = function(param1 = 1, param2 = 2)
extract {paramter1:1, param2:2}
my current code is:
def dump_args(func):
def wrapper(*args, **kwargs):
variables = {}
func_args = signature(func).bind(*args, **kwargs).arguments
func_args = dict(func_args)
# print(func_args)
# to get values that are not passed and defautlt values
sig = signature(func)
for param in sig.parameters.values():
if ( param.default is not param.empty):
if param.name not in func_args:
if type(param.default) in [int, str, float, bool]:
func_args[param.name] = param.default
else:
if param.default == 0:
del func_args[param.name]
print(func_args)
variables = {**variables, **{key: value for key, value in func_args.items() if type(value) in [int, float, bool, str] and key not in variables}}
print(variables)
# return func(*args, **kwargs)
return wrapper
@dump_args
def test(a, b=4, e=0, c="blah-blah", d= 4.5, val=True):
pass
dic= {'name': 'sparsh'}
test(1, 'hola', dic, False)
Output is like this: {'a': 1, 'b': 'hola', 'c': False, 'd': 4.5, 'val': True} {'a': 1, 'b': 'hola', 'c': False, 'd': 4.5, 'val': True}
what i want to do is when i put the decorator in below function like
@dump_args(b = stringvalue)
def test(a, b=4, e=0, c="blah-blah", d= 4.5, val=True):
pass
and this function is called then in the final dictionary the b
key will be replaced by integervalue
key and output should be like this:
{'a': 1, 'stringvalue': 'hola', 'c': False, 'd': 4.5, 'val': True}
{'a': 1, 'stringvalue': 'hola', 'c': False, 'd': 4.5, 'val': True}
can anyone tell me how to do this. Thanks in advance
CodePudding user response:
There are lots of SO questions and answers for your base question of how to add parameters to decorators: Decorators with parameters? , How do I pass extra arguments to a Python decorator?
In your case, you could wrap your existing decorator in another layer that accepts keyword arguments as well and those keyword args would be available in the scope of your inner wrapper. Here's a simpler case along the lines of your full case that illustrates what I mean:
def dump_factory(**dump_kwargs):
def dump_args(func):
def wrapper(**kwargs):
variables = kwargs
# check if any of the kwargs from the outer decorator
# have been set, and replace them here if so
for ky, val in dump_kwargs.items():
if ky in variables:
variables[ky] = val
return func(**variables)
return wrapper
return dump_args
@dump_factory(b=1)
def test(a =0, b=4, e=0, c="blah-blah", d= 4.5, val=True):
print(f" b = {b}")
test(b='a')
# b = 1