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.
*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.
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.
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.
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.
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'}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With