-1

When I have a function with bunch of optional arguments

def function_name(arg1=0, arg2=0, arg3=0, arg4=0, ...):
      .....doing anything

and I want to pass same value to some of them

function_name(arg1=1, arg3=1, arg6=1)

Is there a more compact way to do it? so I don't have to keep copying =value and filling up the line.

After several helpful replies I think I came to the answer I was looking for:

def myargs(value, *args):
    kargs = {}
    for arg in args:
        kargs[arg] = value
    return kargs


function_name(**myargs(1, 'arg1', 'arg3', 'arg6'))

Thanks guys, sorry if I was bad at explaining what I needed.

Ruler555
  • 3
  • 2
  • how many optional args are there? do they always have the same value? passing 3 arguments seems hardly a problem, you could make a dict kwargs mapping alternatively – Chris_Rands Feb 07 '20 at 13:29
  • I'm guessing around 30. Not my function. I need to pass less than 10. It's not really a problem, was just wondering if there was a better way to do it. – Ruler555 Feb 07 '20 at 13:38

5 Answers5

0

You can use default arguments:

def func(arg1, arg2, def_arg1="1", def_arg2="2"):
    pass
Raymond Reddington
  • 1,709
  • 1
  • 13
  • 21
0

You can just use **kwargs

def function_name(arg, argOpt1=0, argOpt2=0, **kwargs):
    pass

kwargs = {"argOpt1" : 123, "argOpt2" : 234} 
function_name('argument1', kwargs)

Look at this and this

mzavarez
  • 61
  • 8
0

If the arguments that are to have the same value are contiguous, then:

def function_name(arg1=0,arg2=0,arg3=0,arg4=0):
    print(arg1, arg2, arg3, arg4)

function_name(2, *[1] * 3)

Prints:

2 1 1 1
Booboo
  • 38,656
  • 3
  • 37
  • 60
  • That would work if I wanted to pass all of them or first few in order. In my case I might need to pass arg2 and arg4 and so on out of order and not all of them. – Ruler555 Feb 07 '20 at 13:48
0

I think what you are wanting to do is keyword argument unpacking. You can pass a dictionary to the function and it will unpack the arguments you have included. Anything not included uses the default values.

def test(w=0, x=0, y=0, z=0):
    return w+x+y+z

kwargs_1 = {'y': 1}
kwargs_2 = {'x': 2, 'z': 3}

test(**kwargs_1)
# returns:
1
test(**kwargs_2)
# returns:
5
James
  • 32,991
  • 4
  • 47
  • 70
0

If you didn't write that function, and you can't change its signature, you can pass the right number of arguments that way :

function_name(*(0,) * function_name.__code__.co_argcount)

It will pass the same value (in that case 0) to all the arguments the function expects.

If you need to pass only 10 arguments for instance, you can write :

function_name(*(0,) * 10)

If you want to target specific arguments by their position and not their names, you can use this :

import inspect


def func(a, b, c=None, d='foo', e=False):
    print(a, b, c, d, e)


def fill_args(fun, value, arg_numbers):
    return {
        name: value
        for name in (
            tuple(inspect.signature(fun).parameters)[i]
            for i in arg_numbers
        )
    }


if __name__ == '__main__':
    func(**fill_args(func, 0, (0, 1, 2)))
    func(**fill_args(func, 'bar', (0, 1, 4)))
    func(**fill_args(func, True, (0, 1, 3)))
znarf94
  • 41
  • 1
  • 5
  • All of the arguments are optional. I need to pass values to specific ones. From my understanding your solution will only pass values to first 10 arguments. While I might need to pass same value to 5th 7th 11th etc argument, leaving rest as defaults. – Ruler555 Feb 07 '20 at 13:59