FunctionsChapter 51 of 114
Default Values
Make a parameter optional, and avoid the shared-default trap.
Giving a parameter a default
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}")
greet("Ada")
greet("Ada", "Good morning")
greet("Ada", greeting="Hi")Output
Hello, Ada Good morning, Ada Hi, Ada
A default makes the parameter optional. The caller can ignore it entirely.
Defaults come last
Parameters with defaults must follow those without, because otherwise Python could not tell which one a positional argument meant:
def greet(greeting="Hello", name): # SyntaxError
passEvaluated once, at definition time
This is the rule behind the most notorious Python gotcha. The default expression runs when def runs, not on each call:
def add(item, target=[]):
target.append(item)
return target
print(add("a"))
print(add("b"))
print(add("c"))Output
['a'] ['a', 'b'] ['a', 'b', 'c']
One list, created once, shared by every call. The same applies to dictionaries, sets and anything else mutable.
It also applies to values computed at definition time, which is why a timestamp default freezes at import:
def stamp(when=None):
if when is None:
when = "computed at call time"
return when
print(stamp())Output
computed at call time
The fix
Use None as the default and build the real one inside:
def add(item, target=None):
if target is None:
target = []
target.append(item)
return target
print(add("a"))
print(add("b"))Output
['a'] ['b']
Test with is None rather than truthiness. An empty list the caller deliberately passed is falsy, and if not target: would silently replace it:
def add(item, target=None):
if target is None:
target = []
target.append(item)
return target
mine = []
add("a", mine)
print(mine)Output
['a']
Immutable defaults are fine
Numbers, strings, True, False, None and tuples cannot be changed, so sharing them is harmless:
def repeat(text, times=2, sep="-"):
return sep.join([text] * times)
print(repeat("ab"))
print(repeat("ab", 3, "+"))Output
ab-ab ab+ab+ab
Defaults are visible
They are stored on the function object, which is occasionally useful and also shows plainly that they are computed once:
def greet(name, greeting="Hello"):
pass
print(greet.__defaults__)Output
('Hello',)Choosing good defaults
Pick the value the caller would have chosen most of the time, and make the dangerous option the one they have to ask for:
def save(data, overwrite=False):
return f"saving {data}, overwrite={overwrite}"
print(save("report"))
print(save("report", overwrite=True))Output
saving report, overwrite=False saving report, overwrite=True
Test yourself
2 questionsWhen is a default value evaluated?
Show the answer
Once, when the def runs — That single evaluation is exactly why a mutable default is shared between calls.
Why test 'if target is None' rather than 'if not target'?
Show the answer
An empty list the caller passed deliberately is falsy and would be replaced — Absence and emptiness are different questions, and only one of them means 'use the default'.
Return Values
Hand a result back, return several things, and leave early.