Python functions can be declared to accept an open-ended number of positional or named inputs. Two special syntax forms—*args and **kwargs—make this posisble without hard-coding every parameter in advance.
Collecting Extra Positional Values with *args
Prefixing a parameter with a single asterisk instructs the enterpreter to bundle any surplus positional arguments into a tuple. Inside the body, you can iterate or index this tuple like any other sequence.
def total(*numbers):
acc = 0
for n in numbers:
acc += n
return acc
print(total(5, 7, 9)) # 21
print(total(1, 2, 3, 4, 5)) # 15
Gathering Arbitrary Keyword Arguments with **kwargs
Two asterisks in front of a parameter name collect any extra keyword arguments into a dictionary whose keys are the argument names and whose values are the supplied data.
def build_profile(**fields):
for k, v in fields.items():
print(f"{k}: {v}")
build_profile(name="Alice", age=28, city="Berlin")
# name: Alice
# age: 28
# city: Berlin
Mixing Fixed, Positional-Variable, and Keyword-Variable Parameters
All three kinds of parameters can coexist in one signature, provided they appear in the order: positional, *args, then **kwargs.
def log_event(level, message, *extras, **meta):
print(f"[{level}] {message}")
if extras:
print("Extra data:", extras)
for key, val in meta.items():
print(f" {key} -> {val}")
log_event("WARN", "Disk space low", "/var", "/tmp",
source="monitoring", timestamp="2024-06-12T09:41:00Z")
# [WARN] Disk space low
# Extra data: ('/var', '/tmp')
# source -> monitoring
# timestamp -> 2024-06-12T09:41:00Z