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.

+3


source to share


3 answers


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.

+3


source


def foo(a, b, c):
    return call_other(round(a),round(b),round(c))

      

or



def foo(a, b, c):
    return call_other(a+1,b+1,c+1)

      

I think if I understand what you are trying to do ... (from reading comments)

+2


source


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.

0


source







All Articles