Master

Functions that change nothing

A function that only reads its inputs and returns a value is called pure. It changes nothing around it, which is what makes it safe to run twice and easy to trust.

What you will see

[1, 2, 3]

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

Tell pure from impure by what changes.

1

Call a pure function twice and compare.

def area(w, h): return w * h print(area(2, 3) == area(2, 3))

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

What it prints
True
2

Show a function that changes an outside name.

total = 0 def bump(n): global total total = total + n bump(2) bump(3) print(total)

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

What it prints
5
The answer depends on how many calls ran. That is the signature of a side effect.
3

Compare a sorting that copies with one that changes.

items = [3, 1, 2] print(sorted(items)) print(items)

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

What it prints
[1, 2, 3] [3, 1, 2]
4

Now use the in-place sort and watch the caller list change.

items = [3, 1, 2] items.sort() print(items)

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

What it prints
[1, 2, 3]
sort changes the list you hold. sorted gives you a new one and leaves yours alone.

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 pure function reads only its inputs and writes only its return value, so the same inputs always give the same output.
1 inputs given
↓
2 body only computes
↓
3 value returned
↓
4 nothing outside changed
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 area(w, h): sets nothing on screen
return w * h sets nothing on screen
print(area(2, 3) == area(2, 3)) True
Why this works
Inputs and outputs only

A pure function gets everything it needs from its parameters and gives back only a return value. That contract is checkable by reading the signature.

Where side effects belong

Side effects are not wrong, they are a decision. Put the effect in the function that owns the change, and keep the calculation functions pure so they can be tested alone.

Examples

Pure in practice

def area(w, h):
    return w * h

print(area(2, 3))
print(area(2, 3))

The same inputs give the same answer every time. Nothing outside the function is touched, so order does not matter.

The impure kind

total = 0

def bump(n):
    global total
    total = total + n

bump(2)
bump(3)
print(total)

This reads and writes a name from outside. The answer now depends on how many times it ran, which is harder to follow.

A side effect is a change

def log(text):
    print(text)

log("start")

Printing is a side effect: it changes what the reader sees, not a value. Side effects are fine, but a function that both returns and changes things is the confusing kind.

Why purity is worth naming

def clean(items):
    return sorted(items)

def messy(items):
    items.sort()
    return items

clean returns a new list and leaves the caller list alone. messy changes the caller list, which can surprise whoever holds it.

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.

← Optional arguments
Previous Lesson
Optional arguments
Next Lesson
Designing the parts a program shares
Designing the parts a program shares →