Understand *args and **kwargs in Python

Collect and unpack arguments, define keyword-only parameters, avoid duplicate values, and preserve object-sharing semantics when forwarding calls.

Best practices
Python programming and application logging

In a function definition, *args collects extra positional arguments into a tuple, while **kwargs collects extra keyword arguments into a dictionary. In a call, * expands an iterable into positional arguments and ** expands a mapping into keyword arguments.

Collect arguments

def demo(first, *args, **kwargs):
    print(first)
    print(args)
    print(kwargs)

demo(1, 2, 3, keyword1=5, keyword2=6)
# 1
# (2, 3)
# {'keyword1': 5, 'keyword2': 6}

Explicitly declared parameters consume their matching arguments first. args and kwargs are naming conventions; *values and **options work the same way.

Unpack a call

def add(a, b):
    return a + b

numbers = [1, 2]
options = {"b": 10}
print(add(*numbers))      # 3
print(add(5, **options))  # 15

The * operand can be an iterable, not just a list. The ** operand must be a mapping with string keys, and those keys still have to fit the function signature unless it accepts extra keywords. Supplying the same parameter twice raises TypeError, even when the duplicate values are equal.

Forward calls without exposing argument data

import logging

logger = logging.getLogger(__name__)

def logged_call(func, *args, **kwargs):
    logger.info("Calling %s", getattr(func, "__name__", type(func).__name__))
    return func(*args, **kwargs)

This passes the objects through without copying them. Avoid logging all raw arguments by default: passwords, tokens, or large objects may be present.

Define keyword-only and positional-only parameters

def configure(name, /, *values, timeout=10, **options):
    return name, values, timeout, options

print(configure("worker", 1, 2, timeout=5, retries=3))

Parameters before / are positional-only. Parameters after *args are keyword-only. A bare * introduces keyword-only parameters without collecting extra positional arguments:

def connect(host, *, timeout):
    return host, timeout

connect("example.com", timeout=5)

A general definition orders positional-only parameters, positional-or-keyword parameters, optional *args, keyword-only parameters, and optional **kwargs, following Python's default-value rules.

FAQ

Can unpacking forms be combined? Yes: func(*values, **options) is common. Python also permits multiple unpackings, but duplicate keyword names and conflicting positional bindings still fail.

Can I modify args? The tuple itself is immutable. Converting it to a list lets you change the local collection, but mutable objects inside remain shared with the caller. Mutating one of those objects can still affect the caller.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting