Advanced

Optional arguments

A parameter can carry a default, so the caller may leave it out. Defaults are how a function has a normal case and still allows a change.

What you will see

[1] [2]

About 2 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Give a parameter a default and use it.

1

Define a function with a default greeting.

def greet(name, greeting="hi"): return greeting + " " + name print(greet("Ada"))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
hi Ada
2

Override the default at the call.

print(greet("Ada", "yo"))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
yo Ada
3

Pass a named argument to change the separator.

def join_words(words, sep=" "): return sep.join(words) print(join_words(["a", "b"], sep="-"))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
a-b
4

Use None as a safe default instead of a list.

def add(item, items=None): if items is None: items = [] items.append(item) return items print(add(1)) print(add(2))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
[1] [2]
A list default would be one shared list, so the second call would print [1, 2].

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

A parameter with a default may be left out at the call, and the default value is made once when the function is defined.
1 greeting has a default
↓
2 call leaves it out
↓
3 the default is used
↓
4 a shared list default is reused
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

def greet(name, greeting="hi"): sets nothing on screen
return greeting + " " + name sets nothing on screen
print(greet("Ada")) hi Ada
Why this works
Defaults are the normal case

A default records what usually happens. The caller then only supplies what is different, which is why a good signature has one required part.

The shared default trap

A default value is made once, at definition time. A list or dict default is therefore the same object every call, which is the classic surprise.

Examples

A default value

def greet(name, greeting="hi"):
    return greeting + " " + name

print(greet("Ada"))
print(greet("Ada", "yo"))

The first call leaves greeting out and gets the default. The second replaces it.

Named at the call

def join_words(words, sep=" "):
    return sep.join(words)

print(join_words(["a", "b"], sep="-"))

Naming the argument at the call says which parameter you mean. Order stops mattering.

A default that is a choice

def line(text, width=10):
    return text.ljust(width)

print(line("ok"))
print(line("ok", 6))

The default width is the normal case. The argument is the exception, and both read the same way.

Do not use a mutable default

def add(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add(1))
print(add(2))

A list cannot be a default, since it would be shared between calls. None plus a fresh list is the safe shape.

Too many defaults

def make(a, b=1, c=2, d=3):
    return a + b + c + d

print(make(1))

This works, but a caller has to remember four defaults. Many optional parts is a sign the function should take a dict instead.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Not repeating yourself
Previous Lesson
Not repeating yourself
Next Lesson
Functions that change nothing
Functions that change nothing →