← Back to modules

Module

Functions

Learn how to define reusable tasks in Python with parameters, arguments, and return values, then practice tracing and debugging function calls step by step.

1. why functions matter

Name a task once, reuse it everywhere

A function is a named block of code that performs one clear task. Instead of rewriting the same logic again and again, you define the logic once and call it whenever you need it.

This gives three major benefits: less repetition, easier debugging, and easier reading. If a bug exists in repeated code, you would need to fix it many times. If the logic is in one function, you fix it once.

A practical way to think about functions is this: if you can describe a task with a short verb phrase such as "calculate tax" or "format greeting", that task is a good candidate for a function.

Before and after using a function

# Repeated by hand
subtotal_1 = 12 + 5 + 3
subtotal_2 = 4 + 8 + 2
subtotal_3 = 7 + 1 + 9

# Reusable function
def subtotal(a, b, c):
    return a + b + c

subtotal_1 = subtotal(12, 5, 3)
subtotal_2 = subtotal(4, 8, 2)
subtotal_3 = subtotal(7, 1, 9)

2. function anatomy

Definition, parameters, body, and return

When you write a function in Python, each part has one job:

  • def: starts the function definition.
  • Function name: describes the task.
  • Parameters: placeholders for incoming values.
  • Function body: indented instructions that run on each call.
  • return: sends one value back to the caller.

Important rule: defining a function does not run it. The body only runs when you call the function by name.

Anatomy example

def area_of_rectangle(width, height):  # definition + parameters
    area = width * height            # body
    return area                      # returned value

result = area_of_rectangle(4, 3)     # call

3. parameters and arguments

How values move into a function call

A parameter appears in the function definition. An argument appears in the function call. During the call, Python binds each argument to a matching parameter.

With positional calls, binding happens left to right. The first argument goes to the first parameter, the second to the second, and so on. Default parameters are used when an argument is not provided.

Try it mentally:
If def greet(name, punctuation): and the call isgreet("Ada", "!"), then name receives"Ada" and punctuation receives"!".

Parameter Match-Up

Match each parameter in the function definition to the value it receives from the call.

Challenge 1: Basic positional matching (1/3)

Definition

def greet(name, punctuation):

Call

greet("Ada", "!")

Parameter

name

Parameter

punctuation


4. return values

Returning a value vs printing text

print() and return are often mixed up. They are different actions with different purposes.

  • print() displays text in the console for humans.
  • return sends a value back to code so it can be reused.

A useful rule: if another part of your program needs the result, you should return it.

Side-by-side example

def print_total(a, b):
    total = a + b
    print(total)      # display only

def return_total(a, b):
    total = a + b
    return total      # reusable value

x = return_total(3, 4)  # x now stores 7

Function Machine

Pick a function, choose arguments, and trace exactly how Python returns a value.

String return example

This function receives one text input and returns a new text message.

def greet(name):
    message = f"Hello, {name}!"
    return message

Current call

greet("Ada")

ParameterArgument received
name"Ada"

Execution trace

  1. Python sees the call greet("Ada").
  2. It creates a local variable name = "Ada" inside the function.
  3. The body builds a message string using that local value.
  4. return sends the message back to the caller.

Returned value

"Hello, Ada!"

Python type: str


5. scope and defaults

Local variables and optional parameters

Variables created inside a function are usually local to that function call. That means they exist during the call and are not directly accessible outside.

Default parameters let a function offer optional behavior. If the caller omits that argument, Python uses the default value from the definition.

Scope and defaults in one snippet

def apply_discount(price, percent=10):
    discount_amount = price * (percent / 100)
    final_price = price - discount_amount
    return final_price

print(apply_discount(80))      # uses default percent=10
print(apply_discount(80, 25))  # overrides default

# discount_amount is local to the function body

6. call flow

Call stack storyboard: where execution goes

When one function calls another, execution temporarily moves into the called function, then returns to the original place after a return value is produced.

Understanding this jump-and-return behavior helps you trace nested calls without confusion.

Caller code

Execution starts in normal code, then the function call transfers control into the function.

PythonStage 1 of 4
subtotal = 18
tax = tax_amount(subtotal)
print(tax)

7. practice

Return Value Race

Predicting outputs before running code builds strong function-tracing habits. Try each question, then read the explanation to compare your mental model to Python behavior.

Question 1 of 5

What is stored in result? `def double(x): return x * 2` then `result = double(4)`


8. debugging

Fix the Function Lab

Most function bugs come from a small set of patterns: missing colons, missing returns, wrong indentation, or wrong argument count in a call.

Use the practice set below to diagnose each bug quickly and choose the correct repair.

Question 1 of 5

Which line fixes this definition? `def add(a, b)`


Guided Project

Smoothie Shop Price Calculator

Build a small Python script where each function handles one piece of the pricing logic. This project reinforces decomposition: one task, one function.

Starter state

# TODO: complete each function

def base_price(size):
    pass

def addons_cost(extra_fruit, protein_powder, chia_seeds):
    pass

def final_total(size, extra_fruit, protein_powder, chia_seeds, tax_rate=0.08):
    pass

# TODO: add at least three test calls

Smoothie Shop Price Calculator Checklist

  1. 1.Create base_price(size) to return the starting cost for small, medium, and large sizes.
  2. 2.Create addons_cost(extra_fruit, protein_powder, chia_seeds) to total optional add-ons.
  3. 3.Create final_total(size, extra_fruit, protein_powder, chia_seeds, tax_rate=0.08) that combines base price, add-ons, and tax.
  4. 4.Write three test calls with different order combinations and store each result in a variable.
  5. 5.Print a clean order summary showing subtotal, tax amount, and final total for each test order.
  6. 6.Add one test call that uses default tax and one call that overrides tax with a custom value.