Module 3.1 covered functions with fixed parameter lists. Real AI libraries—PyTorch, Hugging Face Transformers, FastAPI—expose APIs that accept variable numbers of arguments. *args and **kwargs are the Python mechanisms that make those flexible signatures possible.
When you wrap a model call, build a training utility, or write a decorator, you will often forward arguments you did not explicitly name. Understanding *args and **kwargs is essential for reading library source code and writing reusable AI tooling.
Learning Objectives
By the end of this lesson, students should be able to:
- Explain how
*argscollects extra positional arguments into a tuple. - Explain how
**kwargscollects extra keyword arguments into a dictionary. - Unpack sequences and dicts with
*and**at call time. - Write wrapper functions that forward arguments to an inner function.
- Read library signatures like
def train(self, *args, **kwargs)confidently. - Combine positional-only, keyword-only,
*args, and**kwargsin valid orders.
Introduction: Beyond Fixed Parameters
Most beginner functions declare exact parameters: def predict(text, model_id). Library authors cannot predict every argument their users will need—learning rates, random seeds, tokenizer options, HTTP headers. They use *args and **kwargs to accept and forward the rest.
*args— in a definition, gathers extra positional arguments into a tuple namedargs.**kwargs— in a definition, gathers extra keyword arguments into a dict namedkwargs.*iterable/**mapping— in a call, unpacks values into positional or keyword arguments.
def log_and_call(fn, *args, **kwargs):
print(f"Calling {fn.__name__} with {len(args)} positional args")
return fn(*args, **kwargs)
def add(a, b, c=0):
return a + b + c
log_and_call(add, 1, 2, c=3) # prints then returns 6
Forwarding Arguments in Wrappers
The most common AI-engineering pattern is a wrapper that adds behavior (logging, retries, timing) then passes everything through:
def with_retry(func, *args, max_attempts=3, **kwargs):
for attempt in range(1, max_attempts + 1):
try:
return func(*args, **kwargs)
except Exception as exc:
if attempt == max_attempts:
raise
print(f"Attempt {attempt} failed: {exc}")
This pattern appears in API clients, database connectors, and training callbacks. The wrapper does not need to know which arguments the inner function accepts.
| Syntax | Where | Effect |
|---|---|---|
*args | Definition | Tuple of extra positional values |
**kwargs | Definition | Dict of extra keyword pairs |
*seq | Call | Unpack sequence as positional args |
**dct | Call | Unpack dict as keyword args |
args and kwargs.”
Reality: Only the * and ** matter. def f(*items, **options) is valid. Convention uses args/kwargs for readability.
**kwargs can pass invalid keyword names to any function.”
Reality: Python still validates the callee’s signature. Passing an unexpected keyword raises TypeError unless the target accepts **kwargs.
Knowledge Check
- Short Answer: What type is
argsinsidedef f(*args)? Answer: tuple. - True/False:
**kwargsmust appear after*argsin a definition. Answer: True (when both are used). - Write: Unpack
params = {"lr": 0.01, "epochs": 5}intotrain(**params). Answer:train(**params)ortrain(lr=0.01, epochs=5). - Multiple Choice: Primary use in library code: (a) hide bugs, (b) forward unknown options, (c) replace type hints, (d) avoid imports. Answer: (b).
- Short Answer: What type is
kwargsinsidedef f(**kwargs)? Answer: dict. - True/False: The names must literally be
argsandkwargs. Answer: False—only*and**matter. - Short Answer: What does
*seqdo at call time? Answer: Unpacks a sequence into positional arguments. - Multiple Choice: Passing an unexpected keyword to a function without
**kwargs: (a) is ignored, (b) raisesTypeError, (c) becomes a global, (d) installs a package. Answer: (b). - True/False: A retry wrapper can call
func(*args, **kwargs)without knowing the inner signature. Answer: True. - Short Answer: Write a call that unpacks
vals = (1, 2)intoadd. Answer:add(*vals).
Key Takeaways
*argsand**kwargscollect extra arguments in definitions.- Unpacking with
*and**at call time forwards them to other functions. - Wrappers, decorators, and library APIs depend on this pattern.
- Next: Generators & Iterators for memory-efficient iteration over large datasets.
Source-code walk: Open a Hugging Face from_pretrained wrapper and trace how **kwargs flows to the underlying config. Students see immediate relevance.
Recap: *args and **kwargs collect and forward flexible arguments; next, learn lazy iteration in Generators & Iterators.