Question

I have a question regarding how to define and call a method with both optional arguments and with a *args parameter in Python. For example,

def test_func(arg1, optional_arg=None, *args):
    ...

And I want to be able to call the method with either of the following statements:

test_func("foo", arg1, arg2, ..., optional_arg="bar")
...
test_func("foo", arg1, arg2, ...) 
# arg1, arg2 ... belongs to *args;
# optional_arg is unset (defaults to None)

Is this possible at all, or do I always have to set optional_arg to something when calling a method like this? I.e. I only want optional_arg to be set when I specifically write optional_arg=... when calling the function.

Was it helpful?

Solution

You should use **kwargs for that.

def test_func(arg1, *args, **kwargs):
    optional_arg = kwargs.get('optional_arg')
    ...

The only limitation is that the keyworded argument (optional_arg) must always be after keywordless arguments

>>> test_func("foo", optional_arg="bar", arg1, arg2, ...)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> test_func("foo", arg1, arg2, ..., optional_arg="bar")
...
>>> test_func("foo", arg1, arg2, ...)
...

OTHER TIPS

Unfortunately the positional arguments force you to specify a value for the named argument even if it has a default value; you cannot get around this.

In Python, the keyword arguments must come last in a function call, you can't call test_func as you did in your first example, optional_arg="bar" must come after all non-keyword arguments.

You could try this kind of workaround:

def test_func(arg1, *args,**optional_arg):
    print arg1 
    print args 
    if 'optional_arg' in optional_arg:
        print optional_arg['optional_arg'] 

test_func("foo", 'v','n',optional_arg="bar")

test_func("foo",'v','n')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top