*args and **kwargs

Collecting however many arguments a caller passes, and unpacking a list or dict back into a call.

Overview

Collecting

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

total(1, 2, 3) gives args = (1, 2, 3). total() gives args = (). The function accepts any number of positional arguments without knowing in advance how many, and inside it args is an ordinary tuple.

Two stars do the same for keyword arguments:

def describe(**kwargs):

describe(name="ana", score=91) gives kwargs = {"name": "ana", "score": 91} — an ordinary dict.

The names are pure convention. *items and **options work identically; the stars carry the meaning. Convention is strong enough here that using different names in a general-purpose helper will raise eyebrows, but in a specific function a descriptive name often reads better.

args_kwargs.py

args_kwargs.py Python 3
Output

                    

unpacking_calls.py

unpacking_calls.py Python 3
Output

                    

Worth knowing

*args collects extra positional arguments into a tuple; **kwargs collects extra keyword ones into a dict.
The names are convention, not syntax. The stars are the syntax.
Order in a definition: normal, then *args, then **kwargs.
At a call site the stars do the reverse - they spread a list or dict back into arguments.

*args and **kwargs: A Practical Guide

One star collects any number of positional arguments into a tuple; two stars collect keyword arguments into a dictionary. At a call site the same stars run in reverse, spreading a collection back out into arguments.

Order in a definition

def report(label, *values, **options):

Named parameters first, then *args, then **kwargs. Python needs the fixed ones before the variable ones so it knows what to bind where.

Spreading

The same star at a call site does the opposite job:

dims = [2, 3, 4]
volume(*dims)    # same as volume(2, 3, 4)

Without the star you pass one argument — the list itself — and get a TypeError about missing parameters. With it, the list is spread across the parameters in order.

** does the same for a dict, matching keys to parameter names:

volume(**{"length": 2, "width": 3, "height": 4})

The pass-through pattern

This is where the two halves meet, and it is by far the most common real use:

def logged(func, *args, kwargs):
    print("calling", func.__name__)
    return func(*args,
kwargs)

logged accepts anything and forwards it untouched. It does not need to know the signature of what it is wrapping. Every decorator, every wrapper, every "do this then call that" helper is built on this shape.

Merging collections

The stars also work when building literals:

[*first, *second]    {defaults, overrides}

The dict form is a neat way to layer configuration: later keys win, so overrides beat defaults.

Check yourself

0 of 3

Answer without scrolling back up.

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

  2. `volume(*[2, 3, 4])` is the same as what?

  3. Why does the wrapper pattern use both `*args` and `**kwargs`?

Cheat sheet

*args and **kwargs

One star collects any number of positional arguments into a tuple; two stars collect keyword arguments into a dictionary. At a call site the same stars run in reverse, spreading a collection back out into arguments.

PYTHON · vizlearn.in/python/args_and_kwargs.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.