Functions — *args, **kwargs, and Defaults
Python · Core Language · Run with python3
Explanation
Python functions support positional args, keyword args, defaults, variadic positional (`*args` → tuple), variadic keyword (`**kwargs` → dict), positional-only params (before `/`), and keyword-only params (after `*`). Functions are first-class: they can be passed, returned, and stored. The default value is evaluated once at definition time — a common gotcha with mutable defaults.
Real-World Scenario
A logging function `log(message, level="INFO", *tags, timestamp=True, **extra)` demonstrates the full parameter spectrum: required positional, default, variadic, keyword-only with default, and extra keywords — all in one signature. ```python def create_connection(host, port=5432, /, *, timeout=30, **options): # host, port: positional-only (before /) # timeout: keyword-only (after *) # options: extra keyword args print(f"Connecting to {host}:{port} (timeout={timeout})") print(f"Extra options: {options}") create_connection("localhost", 5433, timeout=10, ssl=True, retry=3) # *args and **kwargs forwarding def wrapper(*args, **kwargs): print(f"args={args}, kwargs={kwargs}") return sum(args) print(wrapper(1, 2, 3, label="sum")) ```
Quick Snippet
def create_connection(host, port=5432, /, *, timeout=30, **options):
# host, port: positional-only (before /)
# timeout: keyword-only (after *)
# options: extra keyword args
print(f"Connecting to {host}:{port} (timeout={timeout})")
print(f"Extra options: {options}")
create_connection("localhost", 5433, timeout=10, ssl=True, retry=3)
# *args and **kwargs forwarding
def wrapper(*args, **kwargs):
print(f"args={args}, kwargs={kwargs}")
return sum(args)
print(wrapper(1, 2, 3, label="sum"))Full Example
# Compile: python3 functions.py
# Output:
# Connecting to localhost:5433 (timeout=10)
# Extra options: {'ssl': True, 'retry': 3}
# args=(1, 2, 3), kwargs={'label': 'sum'}
# 6
def create_connection(host, port=5432, /, *, timeout=30, **options):
# host, port: positional-only (before /)
# timeout: keyword-only (after *)
print(f"Connecting to {host}:{port} (timeout={timeout})")
print(f"Extra options: {options}")
create_connection("localhost", 5433, timeout=10, ssl=True, retry=3)
def wrapper(*args, **kwargs):
print(f"args={args}, kwargs={kwargs}")
return sum(args)
result = wrapper(1, 2, 3, label="sum")
print(result)
# Mutable default pitfall — use None instead
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [2] — not [1, 2]!
python3 functions.py