Python *args and **kwargs

Learn Python *args and **kwargs with simple examples. Understand positional arguments, keyword arguments, how to iterate over kwargs, and how to pass args and kwargs to another function.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

Python *args and **kwargs

*args and **kwargs extend a function so callers can pass extra positionals or keywords beyond the named parameters. For general def syntax, see Python function examples.

python
def show_args(*args):
    print(args)

show_args(1, 2, 3)
Output

You should see (1, 2, 3).

python
def show_kwargs(**kwargs):
    print(kwargs)

show_kwargs(name="Alice", age=30)
Output

You should see {'name': 'Alice', 'age': 30}. The * form collects positionals into a tuple; the ** form collects keywords into a dict.

Tested on: Python 3.13.3; kernel 6.14.0-37-generic.


What are *args and kwargs in Python?

They are optional parameter forms in a function definition. Normal parameters bind first; anything left over goes into args or kwargs. The language reference documents the full parameter grammar, including /, *, and keyword-only sections. Only the * and ** prefixes are special—the names args and kwargs are convention; *pieces and **options are valid, but most teams keep the usual names for readability.


Python *args example

python
def total(*nums):
    return sum(nums)

print(total(10, 20, 5))
Output

That prints 35. Inside the function the parameter is always a tuple (even for a single extra value, and () when nothing extra is passed). You can loop it like any iterable—pair with enumerate() when you want an index alongside each extra positional:

python
def dump(*args):
    for i, arg in enumerate(args):
        print(i, arg)

dump("a", "b")
Output

You should see 0 a then 1 b. Required parameters still come first in the signature; *args only captures what remains after those bind:

python
def line(prefix, *parts):
    return prefix + ": " + " | ".join(parts)

print(line("INFO", "start", "ok"))
Output

That prints INFO: start | ok.


Python kwargs example

python
def greet(**info):
    parts = [f"{k}={v}" for k, v in info.items()]
    return ", ".join(parts)

print(greet(role="admin", region="EU"))
Output

You should see role=admin, region=EU. The parameter behaves like a normal dict of names to values. To walk every keyword the caller sent, iterate kwargs.items():

python
def print_details(**kwargs):
    for key, value in kwargs.items():
        print(key, value)

print_details(name="Alice", age=30, city="Delhi")
Output

Expect three lines: name Alice, age 30, city Delhi (insertion order for built-in dicts in current CPython). When a key might be missing, use .get instead of indexing:

python
def opts(**kwargs):
    timeout = kwargs.get("timeout", 5)
    return timeout

print(opts(timeout=10))
print(opts())
Output

That prints 10 then 5.


Difference between *args and kwargs

Aspect *args **kwargs
Caller syntax Extra positionals Extra name=value keywords
Inside function tuple dict
Typical use Varargs, forwarding positionals Options bags, forwarding keywords

Use *args and kwargs together

Python expects this order in the header: normal parameters (and optional /), *args if present, keyword-only parameters, then **kwargs if present. Violating that order is a SyntaxError on the def line. A typical pattern keeps one required value, scoops variadic tags, and still accepts arbitrary metadata:

python
def record(title, *tags, **meta):
    print("title:", title)
    print("tags:", tags)
    print("meta:", meta)

record("Post", "python", "tips", views=120, draft=True)
Output

Expect title: Post, tags: ('python', 'tips'), and meta with views and draft.


Pass *args and kwargs to another function

Forwarding reuses the same unpacking syntax the inner function expects. Positionals only:

python
def inner(a, b):
    print(a, b)

def wrap_args(*args):
    return inner(*args)

wrap_args(1, 2)
Output

That prints 1 then 2. Keywords only:

python
def inner(x=0, y=0):
    print(x, y)

def wrap_kwargs(**kwargs):
    return inner(**kwargs)

wrap_kwargs(x=3, y=4)
Output

That prints 3 then 4. Both together (the usual wrapper):

python
def display_user(name, age, city=None):
    print(name, age, city)

def wrapper(*args, **kwargs):
    return display_user(*args, **kwargs)

wrapper("Alice", 30, city="Delhi")
Output

That prints Alice 30 Delhi.


Common mistakes with *args and kwargs

  • Wrong header order (**kwargs before *args, keyword-only slots misplaced) causes SyntaxError—fix the definition line before chasing callers.
  • Overusing catch-alls when the parameter set is fixed; typos like regoin="EU" hide inside **kwargs and skip type checkers—prefer explicit parameters for public APIs.
  • Silent extra keys in **kwargs; validate or reject unknown keys when extensions are not intended.
  • Calling inner(args, kwargs) instead of inner(*args, **kwargs)—you would pass the tuple and dict as single objects.
  • Expecting sorted kwargs iteration—use sorted(kwargs) when you need a stable order.

Python args and kwargs quick reference table

Need Syntax
Accept any number of positional arguments def func(*args):
Accept any number of keyword arguments def func(**kwargs):
args type inside function tuple
kwargs type inside function dict
Use both together def func(*args, **kwargs):
Pass args to another function other_func(*args)
Pass kwargs to another function other_func(**kwargs)
Pass both to another function other_func(*args, **kwargs)
Iterate over args for arg in args:
Iterate over kwargs for key, value in kwargs.items():

Summary

*args is a tuple of extra positionals; **kwargs is a dict of extra keywords. Pair required parameters with *args / **kwargs using Python’s fixed ordering, iterate args or kwargs.items() when you need to inspect values, and forward with inner(*args, **kwargs) so callees see the original call shape. Prefer explicit parameters when the API is stable, and validate open-ended kwargs when typos would otherwise slip through. Short option bags sometimes pair well with a lambda wrapper when the forwarding logic stays one expression.


References


Frequently Asked Questions

1. What type are *args and **kwargs inside the function?

*args is a tuple of extra positional values; **kwargs is a dict of extra keyword names to values.

2. How do I forward arguments to another function?

Call inner(*args, **kwargs) from a wrapper that accepts *args and **kwargs so both positional and keyword bundles pass through unchanged.

3. Do I have to name them args and kwargs?

No—the stars matter; names are convention only, but using args and kwargs keeps code readable for others.

4. Can I put **kwargs before *args?

No—parameters must follow the ordering rules: normal args, then *args, then keyword-only parameters, then **kwargs.
Bashir Alam

Data Analyst and Machine Learning Engineer

Computer Science graduate from the University of Central Asia, currently employed as a full-time Machine Learning Engineer at uExel. His expertise lies in OCR, text extraction, data preprocessing, and …