pvdocs /Python/"*args / **kwargs"

args / *kwargs

Special syntax for functions that accept a variable number of arguments.

*args — Variadic Positional Arguments

Collects extra positional arguments into a tuple.

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

total(1, 2, 3)       # 6
total(10, 20)        # 30
total()              # 0

**kwargs — Variadic Keyword Arguments

Collects extra keyword arguments into a dict.

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

show_info(name="Alice", age=30, city="NYC")

Using Both

def func(a, b, *args, **kwargs):
    print(a, b)       # required positional
    print(args)       # extra positionals as tuple
    print(kwargs)     # extra keywords as dict

func(1, 2, 3, 4, x=10, y=20)
# 1 2
# (3, 4)
# {'x': 10, 'y': 20}

Argument Order Rules

def func(positional, *args, keyword_only, **kwargs)
  1. Regular positional parameters
  2. *args (or bare * to stop positionals without collecting)
  3. Keyword-only parameters (after *)
  4. **kwargs
def func(a, b, *, force=False):  # force is keyword-only
    ...

func(1, 2, force=True)   # OK
func(1, 2, True)         # TypeError — force must be named

Positional-Only Parameters (Python 3.8+)

Use / to make parameters positional-only:

def func(a, b, /, c):
    ...

func(1, 2, c=3)   # OK
func(a=1, b=2)    # TypeError — a and b must be positional

Unpacking with * and **

nums  = [1, 2, 3]
dct   = {"name": "Alice", "age": 30}

print(*nums)           # print(1, 2, 3)
func(*nums)            # func(1, 2, 3)
func(**dct)            # func(name="Alice", age=30)

# Merge dicts (Python 3.9+: use | operator)
merged = {**dct, "city": "NYC"}

# Merge / unpack lists
combined = [*nums, 4, 5]   # [1, 2, 3, 4, 5]

Forwarding Arguments

def wrapper(*args, **kwargs):
    # Pre-processing...
    return original_func(*args, **kwargs)

Key Interview Points