Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python trying to place keyword arguments after *args

I'm a bit confused about using *args.

I want to write a function that takes a variable number of arguments but can still use the advantage of defining a predefined value for a keyword argument.

But it's not possible to write a function like this:

def foo(*args, bar = "foo"):
    print bar, args

It's just possible to write it like this:

def foo2(bar = "foo", *args):
    print bar, args

But then I call foo2 and pass the first argument it overrides the default value for bar!.

foo2("somevalue")
somevalue ()

Is where a way of doing this better ??

I know I could write it like this:

def foo(*args, **kwargs):
    kwargs["bar"] = "foo"

but something like the first method definition (which yields a syntax error) is more intuitive from my point of view.

like image 768
user2221323 Avatar asked Mar 16 '14 11:03

user2221323


People also ask

What does * arg do in Python?

*args allows us to pass a variable number of non-keyword arguments to a Python function. In the function, we should use an asterisk ( * ) before the parameter name to pass a variable number of arguments.

How do I set keyword arguments in Python?

Embrace keyword arguments in Python Consider using the * operator to require those arguments be specified as keyword arguments. And remember that you can accept arbitrary keyword arguments to the functions you define and pass arbitrary keyword arguments to the functions you call by using the ** operator.

Can keyword arguments be followed by positional arguments?

The error positional argument follows keyword argument means that the if any keyword argument is used in the function call then it should always be followed by keyword arguments. Positional arguments can be written in the beginning before any keyword argument is passed.

Should you use keyword arguments in Python?

Use the Python keyword arguments to make your function call more readable and obvious, especially for functions that accept many arguments. All the arguments after the first keyword argument must also be keyword arguments too.


2 Answers

You would use kwargs and do the assignment in the call not the definition:

def foo2(*args, **kwargs):     # kwargs takes our key/values arguments
    print args, kwargs

foo2(1, 2, 3, bar="foo")       # bar is assigned to in call when using kwargs 

Which gives:

(1, 2, 3) {'bar': 'foo'} 

You could use get to set foo as a default for bar like so:

def foo2(*args, **kwargs):
    kwargs["bar"] = kwargs.get("bar", "foo") # if bar is not set use foo as val
    print args, kwargs

foo2(1, 2, 3, bar="foo")
foo2(1, 2, 3, bar="notfoo")
foo2(1, 2, 3)

So that kwargs["bar"] is always foo unless explicitly changed:

(1, 2, 3) {'bar': 'foo'}
(1, 2, 3) {'bar': 'notboo'}
(1, 2, 3) {'bar': 'foo'}
like image 174
Chris Seymour Avatar answered Oct 12 '22 21:10

Chris Seymour


Can you switch to python 3 ?, In Python 3 you can use your first approach:

def foo(*args, bar = 'default_value'):
    print (args, bar)

foo(bar = 'newval')
foo('hola2')

You'll get:

() newval
('hola2',) default_value
like image 43
Roberto Avatar answered Oct 12 '22 21:10

Roberto