Python way of changing function arguments inside a function
Let's say that I have a list of integer arguments in a function and I want to add 1 to each one. Is there a clean way to do this, something like this pseudocode:
def foo(a, b, c):
for argument in arguments:
argument += 1
...
In particular, I want to avoid explicitly referring to each of these arguments inside the code and just iterate over all the arguments. Changing function arguments for a list only is not an option, as it a, b, c
has a specific meaning within the code.
source to share
With explicit reference
A clean way to do this is probably with iterative unboxing and display, like this:
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 it is still explicit, and also stores the parameters in the function signature foo
.
Of course, you can use the *args
and **kwargs
and control them (directly), but it can lead to loss of information about what the parameters mean a
, b
and c
(its semantics).
Using a decorator (apply a function across all parameters)
Another way to do this, to 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 a decorator on foo
, for example:
@apply_func_args(round)
def foo(a,b,c):
# ...
Now, if you call foo(1.4,1.3,1.9)
, foo
receive (a,b,c) == (1,1,2)
. For example, if you want 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 have defined a clean way to apply the ( round
) function to all named and unnamed parameters foo
. As a result, if we name foo
, foo
it will always get rounded values.
source to share
Here's an example with no side effects:
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
c = [9, 8, 7, 6]
def foo(*args):
modified = list()
for idx, arg in enumerate(args):
modified.append([x + 1 for x in arg])
print modified
# do something else
# In [17]: foo(a, b, c)
# [[2, 3, 4, 5], [6, 7, 8, 9], [10, 9, 8, 7]]
With this implementation, you can enter as many arrays as you like.
source to share