TracksPractical Coding FoundationsFunctionsPure and Impure Functions(6 of 9)

Pure and Impure Functions

Not all functions behave the same way. Some functions take inputs, calculate a result, and return it — nothing else happens. Others print messages, modify lists, or depend on external data. Understanding this distinction helps you write more predictable, testable code.

Pure Functions

A pure function has two characteristics:

  1. Same input always produces same output — call it with (3, 5) and you'll always get the same result
  2. No side effects — it doesn't change anything outside itself
def add(a, b):
    return a + b

def calculate_area(width, height):
    return width * height

These functions are predictable. You can call them a thousand times with the same inputs and always get the same outputs. They don't print anything, modify any lists, or depend on global variables.

Impure Functions

An impure function either produces side effects or depends on external state:

# Side effect: prints to screen
def greet(name):
    print(f"Hello, {name}!")

# Side effect: modifies input list
def add_item(shopping_list, item):
    shopping_list.append(item)

# Depends on external state
counter = 0
def increment():
    global counter
    counter = counter + 1
    return counter

These functions do more than calculate values. They change things in the outside world or behave differently depending on external conditions.

Why This Matters

Pure functions are easier to test. You just check that inputs produce expected outputs:

# Easy to test
def add(a, b):
    return a + b

assert add(2, 3) == 5  # Simple!

Pure functions are easier to understand. You don't need to track what else they might affect.

Pure functions are easier to reuse. They don't depend on specific global variables or system state.

When Impure Is Necessary

Programs need to interact with the world. You have to print output, save files, send network requests, and update databases. These are all side effects, and they're essential.

The goal isn't to eliminate impure functions — it's to be intentional about them. Keep your calculation logic in pure functions, and use impure functions specifically for interacting with the outside world.

# Pure: just calculates
def calculate_total(items):
    return sum(item["price"] for item in items)

# Impure: interacts with user
def display_total(total):
    print(f"Your total is ${total:.2f}")

# Use them together
total = calculate_total(cart_items)  # Pure calculation
display_total(total)                  # Impure output

This separation makes your code more organized and testable.

See More

Further Reading

You need to be signed in to leave a comment and join the discussion