ReviseAlgo Logo

Functions

*args and **kwargs

Variable-length positional and keyword arguments

Interview: Very common in interviews — essential for decorators, wrappers, and flexible APIs

Last Updated: June 12, 2026 9 min read

args and *kwargs allow functions to accept a variable number of arguments. args collects extra positional arguments into a tuple, while *kwargs collects extra keyword arguments into a dictionary. These are fundamental for writing flexible APIs, decorators, and wrapper functions.

args (Variable Positional)

  • Collects extras: Any positional arguments beyond the defined parameters go into args as a tuple
  • Can be empty: If no extra positional args are passed, args is an empty tuple ()
  • Name convention: The name "args" is convention — technically *anything works, but *args is standard
  • Unpacking: The operator also unpacks iterables when calling — func(*[1, 2, 3])

kwargs (Variable Keyword)

  • Collects extras: Any keyword arguments not in the defined parameters go into kwargs as a dict
  • Can be empty: If no extra keyword args are passed, kwargs is an empty dict {}
  • Unpacking: also unpacks dicts when calling — func(**{"a": 1})
  • Order preserved: kwargs maintains insertion order since Python 3.7

The Decorator Pattern

The most important use of args/*kwargs is in decorator wrappers: def wrapper(*args, **kwargs): return func(*args, **kwargs). This forwards ALL arguments to the wrapped function without knowing its signature — essential for generic decorators.

Combining All Parameter Types

The full parameter signature follows this order:

  • def func(required, optional=default, *args, keyword_only, **kwargs)
  • Required args must be provided first
  • args captures remaining positional args
  • Keyword-only args (after ) must use keyword syntax
  • **kwargs captures any remaining keyword args

Common Pitfall: in Different Contexts

The operator has different meanings: in function definition, it collects arguments; in function call, it unpacks iterables. Similarly, ** in definition collects kwargs, but in call unpacks dicts. Don't confuse these two uses!

Use Cases

Writing generic decorator wrappers that work with any function signature

Building flexible configuration functions with default + override merging

Creating wrapper/proxy functions that forward all arguments to another function

Designing APIs that accept variable numbers of items (batch operations)

Implementing printf-style debugging with automatic argument logging

Common Mistakes

Forgetting to forward *args, **kwargs in wrapper functions — breaks the wrapped function's signature

Confusing * in definition (collects) vs * in call (unpacks) — they do opposite things

Using mutable default values in combination with **kwargs — dict.update() modifies in-place

Not using functools.wraps in decorators — loses the original function's name and docstring

Accepting **kwargs without documenting what keys are expected — makes the API opaque