*args and **kwargs let you define functions that accept a variable number of arguments. *args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dictionary. The names args and kwargs are conventions—you can use other names, but the single * and double ** are required. This article shows how they work and when they are useful.

What they do

Inside the function, args is a tuple of all extra positional arguments, and kwargs is a dict of all extra keyword arguments. They do not include any arguments that were matched by earlier parameters. See Functions basics and Default arguments for normal parameters.

*args — multiple positional arguments

Use *args when the number of positional arguments is unknown or variable:

def sum_numbers(*args):
    total = 0
    for num in args:
        total += num
    return total

print(sum_numbers(1, 2, 3))        # 6
print(sum_numbers(1, 2, 3, 4, 5))  # 15

You can mix normal parameters with *args. The normal ones get the first arguments; the rest go into args:

def greet(greeting, *names):
    for name in names:
        print(f"{greeting}, {name}!")

greet("Hello", "Alice", "Bob")  # Hello, Alice! / Hello, Bob!

**kwargs — multiple keyword arguments

**kwargs collects any keyword arguments that were not matched by earlier parameters into a dictionary:

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

print_info(name="Alice", age=30, city="NYC")
# name: Alice
# age: 30
# city: NYC

Order of parameters

When you use both, *args must come before **kwargs. The usual order is: normal args, then *args, then keyword-only args (if any), then **kwargs:

def example(a, b, *args, **kwargs):
    print("a:", a, "b:", b)
    print("args:", args)
    print("kwargs:", kwargs)

example(1, 2, 3, 4, x=5, y=6)
# a: 1 b: 2
# args: (3, 4)
# kwargs: {'x': 5, 'y': 6}

Using both: pass-through (e.g. decorators)

Wrappers and decorators often accept *args, **kwargs and pass them to the wrapped function:

def example(*args, **kwargs):
    print("Positional:", args)
    print("Keyword:", kwargs)

def wrapper(func):
    def inner(*args, **kwargs):
        print("Calling", func.__name__)
        return func(*args, **kwargs)
    return inner

When to use them

  • *args: Variable number of positional arguments (e.g. sum, min, or “all remaining”).
  • **kwargs: Flexible options or config (e.g. optional settings, or passing through to another API).
  • Both: Wrappers, decorators, or any function that must forward unknown arguments.

Next steps: Core Concepts · Decorators · Default arguments · Functions