Skip to content
FollowtheDamnCode

*args and **kwargs

Functions that take any number of arguments.

4 minute read

Big idea

*args lets a function take any number of positional arguments, collected into a tuple. **kwargs collects any number of keyword arguments into a dict.

*args

You've already used a function like this — print takes as many values as you give it. Write your own with a * before a parameter name:

Add up any number of values
def total(*numbers):
    print(numbers)
    return sum(numbers)

print(total(1, 2))
print(total(5, 10, 15, 20))
print(total())
output
(1, 2)
3
(5, 10, 15, 20)
50
()
0

Run and edit it in the app.

Inside the function, numbers is a tuple of everything passed. The name args is just a convention; the * is what matters.

Mixing with normal parameters

Normal parameters come first and take the first arguments; *args mops up the rest:

Predict: who gets what?
def announce(title, *names):
    print(title + ":", ", ".join(names))

announce("Winners", "Ada", "Grace", "Linus")
announce("Nobody")
What does it print? Show the answer
Winners: Ada, Grace, Linus
Nobody:

Run and edit it in the app.

**kwargs

Two stars collect keyword arguments into a dict:

A flexible profile
def profile(name, **details):
    print(name)
    for key, value in details.items():
        print(f"  {key}: {value}")

profile("Ada", born=1815, field="mathematics")
output
Ada
  born: 1815
  field: mathematics

Run and edit it in the app.

Unpacking into a call

The stars also work the other way: * spreads a list into separate arguments, ** spreads a dict into keyword arguments.

Spreading a list
def area(width, height):
    return width * height

size = [3, 7]
print(area(*size))
options = {"width": 2, "height": 5}
print(area(**options))
output
21
10

Run and edit it in the app.

Fix the bug: print the largest of all the numbers
def largest(*nums):
    best = nums[0]
    for n in nums:
        if n > best:
            best = n
    return best

values = [4, 19, 7]
print(largest(values))
output
19

Run and edit it in the app.

Without a star, largest(values) passes one argument — the whole list — so nums is ([4, 19, 7],). Call largest(*values) to spread it out.

The full order

When you combine them all, the order is fixed: normal parameters, *args, keyword-only parameters, then **kwargs. Most functions need only one or two of these.

def f(*args): return args — what does f(1, 2, 3) return?

Watch it

Think of it like

A bag at the door of a party: everyone who turns up without a reserved seat (a named parameter) drops their coat in it. *args is the bag for unnamed guests; **kwargs is the bag where every coat has a name tag.

Key terms

  • *args — Collects extra positional arguments into a tuple.
  • **kwargs — Collects extra keyword arguments into a dict.
  • Unpacking in a call — f(*list) or f(**dict) spreads values into arguments.

Check yourself

Inside def f(*args), what type is args?

What does **kwargs collect?

nums = [1, 2]. How do you pass them as two separate arguments to f?