Q&A library Python

What do *args and **kwargs mean in Python?

Python Intermediate argumentsfunctionsunpacking

Short answer

args collects extra positional arguments into a tuple, and kwargs collects extra keyword arguments into a dictionary. The same star syntax also unpacks a sequence or dictionary back into arguments at the call site.

The short version

In a function definition, *args gathers any extra positional arguments into a tuple, and **kwargs gathers any extra keyword arguments into a dictionary. The names are just convention; the stars do the work. At a call site, the same * and ** unpack a sequence or dictionary back into separate arguments.

Collecting arguments

def total(*args):
    return sum(args)

print(total(1, 2, 3))   # 6, args is (1, 2, 3)

args is an ordinary tuple, so you can loop over it or index it. This lets a function accept any number of positional values.

Collecting keyword arguments

def describe(**kwargs):
    for key, value in kwargs.items():
        print(f"{key} = {value}")

describe(colour="red", size="large")

kwargs is a normal dictionary, here {"colour": "red", "size": "large"}.

Using both together

The order is fixed: normal parameters, then *args, then **kwargs.

def log(label, *args, **kwargs):
    print(label, args, kwargs)

log("event", 1, 2, user="ana")   # event (1, 2) {'user': 'ana'}

Unpacking at the call site

The same stars work in reverse, spreading a collection into arguments. This is where the two ideas connect.

values = [1, 2, 3]
print(total(*values))   # same as total(1, 2, 3)

opts = {"colour": "red", "size": "large"}
describe(**opts)        # same as describe(colour="red", size="large")

Where this is genuinely useful

The common real use is a wrapper that passes arguments straight through to another function without needing to know them.

def timed(func, *args, **kwargs):
    # ... start a timer ...
    result = func(*args, **kwargs)
    # ... stop the timer ...
    return result

Here *args, **kwargs let timed forward whatever arguments the wrapped function expects, so one wrapper works for any function.

A caution

Do not reach for *args and **kwargs just to look flexible. Explicit named parameters document what a function accepts and let editors and type checkers help you. Use the star forms when the count really is variable or when you are genuinely forwarding arguments onward.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project