17 · *args, **kwargs, type hints, docstrings
Write flexible, self-documenting functions — variadic args, keyword-only params, type hints, and NumPy-style docstrings.
`*args` collects any number of positional arguments into a tuple; `**kwargs` collects any number of keyword arguments into a dict. Together they let one function accept an open-ended signature — the backbone of scikit-learn estimators and PyTorch layers.
Without this:
Without `**kwargs`, every wrapper function that passes config to an inner call must enumerate every possible hyperparameter by name — adding a new one breaks the wrapper. `**kwargs` makes wrappers future-proof.
*args in a function signature gathers all extra positional arguments into a tuple named args. **kwargs gathers all extra keyword arguments into a dict named kwargs. Both are naming conventions — the real syntax is the * and ** prefixes. You can also use * and ** at the call site to unpack a list or dict into arguments: f(*my_list), f(**my_dict). Keyword-only parameters come after a bare *: def f(a, *, key): — key must always be passed by name. Positional-only parameters come before a /: def f(a, /, b): — a cannot be passed by name.
Python (in browser)
`*args` is a tuple inside the function body — you can iterate it, slice it, or pass it onward with `f(*args)`. The name `args` is a convention; `*values` works just as well.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
`**kwargs` is a plain dict inside the function body. Unpacking a dict at the call site with `f(**d)` is how scikit-learn and PyTorch accept flexible parameter grids.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Type hints like `list[float]` and `-> dict[str, float]` document the contract but are **not enforced at runtime**. Tools like mypy, pyright, and your IDE use them for static analysis.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
NumPy-style docstrings (Parameters / Returns / Examples sections) are the de-facto standard in data-science libraries. IDEs render them as rich hover documentation.
What does calling `f(**{"a": 1, "b": 2})` do?
- `*args` → extra positional args as a tuple; `**kwargs` → extra keyword args as a dict. Use `*` and `**` at the call site to unpack sequences and dicts.
- Keyword-only params (`def f(*, key):`) must always be passed by name — useful for flags that should never be passed by accident.
- Type hints document intent but don't enforce it at runtime. Use mypy/pyright for static checking. NumPy-style docstrings are the standard for scientific Python.
scikit-learn passes hyperparameter grids as `**params` to estimator constructors — `SVC(**{'C': 1.0, 'kernel': 'rbf'})`. Type hints document tensor shapes in PyTorch modules. `**config` unpacks experiment YAML files loaded with PyYAML into training functions. Keras's `model.fit(**training_args)` uses the same pattern.
If you remove it: Without `**kwargs`, a wrapper that passes config to a nested call must hardcode every parameter name. Every time a new hyperparameter is added, the wrapper breaks — making library APIs brittle and forcing users to update call sites across the whole codebase.