I'm am trying to write a python decorator to override a function argument, but I'm really lost to what to be put inside the inner() function. What's the proper way to modify args here?
def override(*override_args, **override_kwargs):
def outer(f):
def inner(*args, **kwargs):
...
...
return inner
return outer
@override('Cat')
def my_function(animal, **kwargs):
print animal
print kwargs
my_function('Mouse', k1='1', k2='10')
def override(*override_args, **override_kwargs):
def outer(f):
def inner(*args, **kwargs):
min_args_length = min(len(args), len(override_args))
args = list(args)
for i in xrange(min_args_length):
args[i] = override_args[i]
kwargs.update(override_kwargs)
return f(*args, **kwargs)
return inner
return outer
@override('Cat', 'male', k1='0')
def my_function(animal, **kwargs):
print animal
print kwargs
my_function('Mouse', k1='1', k2='10')
output:
Cat
{'k2': '10', 'k1': '0'}
explain:
args is a tuple contains args without name, we can override at most min(len(args), len(override_args)) of them.
kwargs is a dict contains named args as key : value pairs. Just update override_kwargs to kwargs
And I strongly suggest you only override named args "kwargs" to prevent mismatch args' order.
class override_func_params(object):
def __init__(self, *args, **kwargs):
self.override_args = args
self.override_kwargs = kwargs
def __call__(self, func):
def wrapper(*args, **kwargs):
if kwargs:
kwargs.update(self.override_kwargs)
if args:
args = list(args)
for index, value in enumerate(self.override_args):
try:
args[index] = value
except IndexError:
break
args = tuple(args)
return func(*args, **kwargs)
return wrapper
@override_func_params('a', k=1)
def foo(*args, **kwargs):
print args, kwargs
Call without arguments.
>>> foo()
>>> (), {}
Call with arguments, the arguments are overrided.
>>> foo('b', k=2)
>>> ('a',), {'k': 1}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With