Skip to content

#206: What Is the Meaning of ** and * in Parameters and Method Calls?

You may run into code examples where the parameters are prefixed with a star or a double star. This little feature of Python comes in handy when we need a bit more flexibility for our methods. Let us explore how that works.

*args: accept a variable number of arguments

If we want to accept a variable number of arguments, we can use the * in front of our parameter name to catch everything that is put into our function:

>>> def foo(*values):
...     for a in values:
...         print(a)
...
>>> foo(1)
1
>>> foo(1, 2, 3, 4, 5)
1
2
3
4
5

**kwargs: accept any keywords (name:"value") as parameters

The **kwargs gives us all keyword arguments as a dictionary:

1
2
3
4
5
6
7
>>> def bar(**settings):
...     for value in settings:
...         print(f"{value}{settings[value]}")
...
>>> bar(first_name="Johnny", last_name="Graber")
first_name - Johnny
last_name - Graber

Mix and match?

We can combine the regular parameters with *arg and **kwarg parameters, as long as we put them in that order:

>>> def foobar(a, b, *c, **d):
...     print(f"a: {a}")
...     print(f"b: {b}")
...     for x in c:
...         print(f"\t{x}")
...     for z in d:
...         print(f"{z} {d[z]}")
...

>>> foobar(1, 2, 'a', 'b', 'c', 'd', name="Johnny", blog="improveAndRepeat")
a: 1
b: 2
        a
        b
        c
        d
name Johnny
blog improveAndRepeat

The *args and **kwargs parameters are optional and can be omitted:

>>> foobar(1, 2, name="Johnny", blog="improveAndRepeat")
a: 1
b: 2
name Johnny
blog improveAndRepeat
>>> foobar(1, 2, 'a', 'b', 'c', 'd')
a: 1
b: 2
        a
        b
        c
        d
>>> foobar(1, 2)
a: 1
b: 2

Unpack iterables with *

We can use the *args when we have multiple values on the right side of an assignment and a smaller number of variables on the left side. In this case the * catches everything that is left over:

1
2
3
4
5
6
7
>>> a, *b, c = [1, 2, 3, 4, 5, 6]
>>> a
1
>>> b
[2, 3, 4, 5]
>>> c
6

The first value goes into a, the last value into c and everything else goes into b.

We can use this syntax with multiple return values from a function as well.

Unpack dictionaries with **

We can use the ** to unpack a dictionary when we call a method. Instead of putting the arguments in the right order, we can let Python do that work for us:

>>> def greetings(name, greeting):
...     print(f"{greeting} {name}")
...
>>> greetings("Johnny", "Hi")
Hi Johnny
>>> params = {"name":"Johnny", "greeting":"Welcome"}
>>> greetings(**params)
Welcome Johnny
>>> params = {"greeting":"Welcome", "name":"Johnny"}
>>> greetings(**params)
Welcome Johnny

The order of the keys does not matter, but the names of the keys must match the names of the parameters.

Conclusion

With *args and **kwargs we can get a lot of flexibility for our functions by using them in the parameter declaration. While this is the most common use case, the unpacking of dictionaries or assigning a variable number of values is something where * and ** are a great help as well. We do not need to overdo it and use them everywhere, but when we have a problem where this solution fits, we should use it.