Master

The contract of a function

A function is a promise: given these kinds of values, it returns this kind of value. Stating the promise in the name and the docstring is how a program documents itself.

What you will see

0

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

Write the promise of a function and keep it true.

1

Name the units in and out.

def celsius_to_fahrenheit(c): return c * 9 / 5 + 32 print(celsius_to_fahrenheit(0))

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

What it prints
32.0
2

Add a docstring that states the empty case.

def average(items): """Return the mean, or 0 for an empty list.""" if not items: return 0 return sum(items) / len(items) print(average([]))

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

What it prints
0
3

Return None for the empty case and say so.

def first(items): """Return the first item, or None for an empty list.""" if not items: return None return items[0] print(first([]))

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

What it prints
None
4

Keep a promise by handling the bad input.

def to_number(text): """Return an int, or 0 if text is not a number.""" try: return int(text) except ValueError: return 0 print(to_number("x"))

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

What it prints
0
The docstring promises 0 for bad text, and the body delivers it. A caller never has to guard again.

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 function states what it takes and what it returns, and the body keeps that promise true for every case.
1 name states the units
↓
2 docstring states the return
↓
3 the edge case is named
↓
4 the body keeps the promise
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 celsius_to_fahrenheit(c): sets nothing on screen
return c * 9 / 5 + 32 sets nothing on screen
print(celsius_to_fahrenheit(0)) 32.0
Why this works
What a contract is

A contract is the promise a function makes about its inputs and outputs. It is what lets a caller use a function without reading it, and what lets the body change without breaking the caller.

Why this is the last lesson

Everything before was about writing a function. This is about using one written by someone else, or by you last month. The contract is the thing that survives, and it is the skill that scales for as long as you write programs.

Examples

Say it in the name

def celsius_to_fahrenheit(c):
    return c * 9 / 5 + 32

print(celsius_to_fahrenheit(0))

The name states the units in and out. A reader of the call knows what 32 means without opening the body.

Write the promise down

def average(items):
    """Return the mean of a list of numbers. Returns 0 for an empty list."""
    if not items:
        return 0
    return sum(items) / len(items)

print(average([2, 4]))

The docstring states the return and the empty case. Anyone using it reads three lines instead of guessing.

State the edge case

def first(items):
    """Return the first item, or None for an empty list."""
    if not items:
        return None
    return items[0]

print(first([]))

Naming the empty case in the docstring is the part that saves the next reader, since it is the case they forget.

Keep the promise true

def to_number(text):
    """Return an int, or 0 if text is not a number."""
    try:
        return int(text)
    except ValueError:
        return 0

print(to_number("7"))
print(to_number("x"))

The body does exactly what the docstring claims. A docstring that lies is worse than no docstring at all.

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.

← Designing the parts a program shares
Previous Lesson
Designing the parts a program shares