Default values, keyword-only parameters & the mutable default trap
Defaults and keyword arguments
Lesson 1 of 20 · 10 min · Module 1: Functions, deeper
Good functions are easy to call correctly. Default values and keyword arguments make calls readable, but one classic mistake makes defaults share data between calls.
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…
- Use default values safely
- Avoid shared mutable defaults
- Require keyword arguments with *
The idea
A default is created once, when the function is defined. A default list such as tags=[] is therefore shared by every call. Use None and create a new list inside. A bare * in the parameter list makes the following parameters keyword-only: callers must write their names.
def greet(name, *, punctuation="!"):
return "Hello, " + name + punctuation
print(greet("Mia", punctuation="?"))
01Defaults are evaluated once
Python evaluates def add(item, items=[]) one time. Every call that relies on the default receives that same list object, so items pile up across calls.
def bad(item, items=[]):
items.append(item)
return items
print(bad(1), bad(2))[1, 2] [1, 2]02None means "not provided"
Using None as the default and creating the list inside the function gives each call a fresh list. The same pattern works for dicts and sets.
03Keyword-only parameters
Everything after a bare * must be named. add_tag("x", lower=False) is clear; add_tag("x", None, False) would hide what False means, so Python refuses it.
Your turn
add_tag(tag, tags=None, *, lower=True). It returns a list containing the existing tags plus tag (lowercased unless lower=False), without duplicates and without changing the list passed in. Calls without tags must never share a list.What the checks look for
- Calls without tags do not share a list
- Keeps the caller’s list unchanged
- Avoids duplicates and respects lower=False
- lower can only be passed by keyword
Take this with you
Use None for mutable defaults, and keyword-only parameters for options.
Go a little further
Add a keyword-only parameter limit that keeps only the last limit tags.