Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way of changing function arguments inside the function

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.

like image 428
Daniyal Shahrokhian Avatar asked Jan 21 '26 02:01

Daniyal Shahrokhian


1 Answers

With explicit referencing

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).

Using a decorator (apply the function on all parameters)

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.

like image 147
Willem Van Onsem Avatar answered Jan 22 '26 15:01

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!