Let's say that I have a list of integer arguments in a function, and I want to add 1 to each one of them. Is there a clean way of doing such, something like this pseudo-code:
def foo(a, b, c):
for argument in arguments:
argument += 1
...
In particular, I want to avoid explicitly referencing each of these arguments inside the code, and just iterate over all the arguments. Changing the function arguments to just a list is not an option, since a, b, c have a specific meaning inside the code.
A clean way to do this is probably using iterable unpacking and a mapping, like:
def foo(a,b,c):
a,b,c = map(lambda x:x+1,(a,b,c))
# ...
Or for rounding:
def foo(a,b,c):
a,b,c = map(round,(a,b,c))
# ...
Since this is still explicit, and furthermore keeps the parameters in the function signature of foo.
You can of course use *args and **kwargs and manipulate these (directly), but that could result in losing information about what the parameters a, b and c mean (their semantics).
Another way to do it, that will remove the semantics of the parameters is using a decorator:
def apply_func_args(func):
def dec(f):
def g(*args,**kwargs):
return f(*map(func,args),**{k:func(v) for k,v in kwargs.items()})
g.__name__ = f.__name__
g.__doc__ = f.__doc__
return g
return dec
Then you can put the decorator on foo, like:
@apply_func_args(round)
def foo(a,b,c):
# ...
Now if you call foo(1.4,1.3,1.9), foo will obtain (a,b,c) == (1,1,2). For example, if you want to print a, b, and c:
>>> def apply_func_args(func):
... def dec(f):
... def g(*args,**kwargs):
... return f(*map(func,args),**{k:func(v) for k,v in kwargs.items()})
... g.__name__ = f.__name__
... g.__doc__ = f.__doc__
... return g
... return dec
...
>>> @apply_func_args(round)
... def foo(a,b,c):
... print((a,b,c))
...
>>> foo(1.4,1.3,1.9)
(1, 1, 2)
>>> foo(1.4,2.5,c=0)
(1, 2, 0)
>>> foo(b=1.4,a=2.5,c=0)
(2, 1, 0)
So here we defined a clean way to apply the function (round) on all named and unnamed parameters of foo. As a result, if we call foo, foo will always obtain rounded values.
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