*args, **kwargs & unpacking calls
Flexible arguments
Lesson 2 of 20 · 10 min · Module 1: Functions, deeper
Some functions should accept any number of values: print() takes as many as you give it. Python collects extra arguments for you.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Collect extra arguments with *args and **kwargs
- Spread lists and dicts into calls
- Keep the order of output predictable
The idea
*parts collects extra positional arguments into a tuple. **params collects extra keyword arguments into a dict. In a call, *items and **options do the opposite: they spread a list or dict into separate arguments.
def total(*numbers):
return sum(numbers)
values = [1, 2, 3]
print(total(*values))
01Collecting
In def f(*parts, **params), f(1, 2, a=3) gives parts == (1, 2) and params == {"a": 3}. The names args and kwargs are only conventions; choose names that explain the data.
def show(*parts, **params):
print(parts, params)
show(1, 2, level="hard")(1, 2) {'level': 'hard'}02Spreading
In a call, * and ** reverse the process. make_url(base, *path, **query) passes each list item and each dict entry as a separate argument.
03Sort for stable output
Dicts keep insertion order, which depends on the caller. Sorting the keys makes URLs identical no matter how the arguments were written, which matters for caching and for tests.
Your turn
make_url(base, *parts, **params). Join base and every part with single slashes (strip slashes at the edges of each piece). If there are params, add ?key=value pairs joined by &, with keys in alphabetical order.What the checks look for
- Joins the path pieces
- Removes duplicate slashes
- Adds sorted query parameters
- Works with only a base, and with unpacked lists and dicts
Take this with you
Star collects in a definition and spreads in a call.
Go a little further
URL-encode the query values with urllib.parse.quote so spaces and symbols are safe.