Why Functions?
You already use functions every day — print() is a function! So is input(), len(), and range(). But what if you could create your own functions that do exactly what you need?
Functions are reusable blocks of code with a name. You define them once, and then you can call (run) them whenever you like — as many times as you want.
What you will learn
- How to define your own functions using
def - How to use parameters and arguments to pass information into a function
- How to use default parameters to make arguments optional
- How to use return values to get information back out
- How to return multiple values from a single function
- How scope affects where variables can be used
- The difference between functions and procedures (important for GCSE exams!)
- How to build functions that call other functions
See Functions in Action
Work through each example below. Read the code, run it, then try the suggestions underneath.
Example 1 — Defining and Calling a Function
The simplest possible function: it takes no information in and just does one thing.
greet() and then calls it. What is the difference between defining a function and calling it? Will anything happen when the def line runs, or only when greet() is called?
Defining a function (the def block) just saves the instructions — nothing is printed yet. Only when greet() is called does the code inside run and "Hello!" appears.
def greet():
print("Hello!")
greet()
- Call
greet()three times in a row. What happens? - Change the message inside the function to something else, then run it again.
- What happens if you remove the line
greet()and only keep thedefblock? Why?
Example 2 — Parameters
Functions become much more useful when you can pass information into them. The values inside the brackets are called parameters.
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
greet("Bob")
greet("Charlie")
- Call
greet()with your own name. - Add a second parameter called
greetingso you can saygreet("Alice", "Good morning"). - What error do you get if you call
greet()without any argument? Read the error message carefully.
Example 3 — Return Values
Sometimes you want a function to give a value back rather than just printing something. That is what return does.
return instead of print(). What is the difference? When line result = add(3, 4) runs, what value gets stored in result?
The function calculates 3 + 4 = 7 and returns it. The value 7 is stored in the variable result. Unlike print(), return sends a value back to the caller so it can be used later.
def add(a, b):
return a + b
result = add(3, 4)
print(result)
- Change the numbers passed to
add()and check the result. - Create a new function called
multiplythat returns the product of two numbers. - Try using the return value directly in a print:
print(add(10, 20)).
Example 4 — Default Parameters
Sometimes you want a parameter to have a default value — a fallback that is used when no argument is provided. You do this by using = in the parameter list.
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
# Calling with both arguments
greet("Alice", "Good morning")
# Calling with only one argument - uses the default
greet("Bob")
# Calling with a different greeting
greet("Charlie", "Hey there")
- Change the default greeting to something else, like
"Hi"or"Welcome". - Add a third parameter with a default value, such as
punctuation="!", and use it in the f-string. - What happens if you put the default parameter before the non-default one? Try
def greet(greeting="Hello", name):and see what Python says.
Example 5 — Multiple Return Values
A function can return more than one value at once by separating the values with commas. Python packs them into a tuple, and you can unpack them into separate variables.
def min_max(numbers):
return min(numbers), max(numbers)
lowest, highest = min_max([4, 7, 1, 9, 3])
print(f"Lowest: {lowest}")
print(f"Highest: {highest}")
# You can also capture both values in one variable
result = min_max([10, 20, 5, 15])
print(f"Result as a tuple: {result}")
- Modify the function to also return the sum of the numbers:
return min(numbers), max(numbers), sum(numbers). Remember to unpack into three variables! - Write a function called
name_partsthat takes a full name like"Alice Smith", splits it, and returns the first name and surname separately.
Example 6 — Functions Calling Other Functions
One of the most powerful ideas in programming: you can build bigger functions out of smaller ones. This is called composition or decomposition — breaking a problem into smaller, manageable parts.
def capitalise_word(word):
"""Return the word with the first letter capitalised."""
return word[0].upper() + word[1:].lower()
def format_name(first, last):
"""Format a full name with proper capitalisation."""
return capitalise_word(first) + " " + capitalise_word(last)
# Test it out
name = format_name("aLiCe", "sMiTH")
print(name)
name2 = format_name("BOB", "jones")
print(name2)
- Add a
format_emailfunction that callsformat_nameand creates an email like"Alice Smith <alice.smith@example.com>". - What would happen if
capitalise_wordwas defined afterformat_namebut before the function calls? Try it! - Write a
format_initialsfunction that takes a first and last name and returns just the initials, e.g."A.S.".
How Functions Work
The anatomy of a function
Every function definition has the same structure:
def say_hello(name):
message = f"Hello, {name}! Welcome."
print(message)
say_hello("Priya")
def— the keyword that tells Python you are defining a functionsay_hello— the function name (you choose this; use snake_case)(name)— the parentheses contain any parameters the function needs:— the colon marks the start of the function body- The indented lines underneath are the body — the code that runs when the function is called
Parameters vs arguments
These two words are often mixed up, but there is a simple difference:
| Term | Where? | Example |
|---|---|---|
| Parameter | In the function definition | def greet(name): |
| Argument | In the function call | greet("Alice") |
Think of the parameter as a label on an empty box. The argument is what you put inside that box when you use the function.
return vs print
This is one of the most important distinctions to understand:
return | print | |
|---|---|---|
| What it does | Gives a value back to the code that called the function | Displays text on the screen |
| Can you store the result? | Yes — x = add(3, 4) | No — x = print("hi") stores None |
| When to use | When you need to use the result later | When you just want to show something to the user |
# Compare return vs print
def add_return(a, b):
return a + b
def add_print(a, b):
print(a + b)
result1 = add_return(3, 4)
result2 = add_print(3, 4)
print(f"result1 = {result1}")
print(f"result2 = {result2}")
Procedures vs Functions — a GCSE distinction
In your GCSE exam, you need to know the difference between a function and a procedure. This catches many students out, so pay close attention:
| Function | Procedure | |
|---|---|---|
| Does it return a value? | Yes — uses return | No — just performs an action |
| Python example | len("hello") returns 5 | print("hello") displays text but returns None |
| Can you store the result? | Yes — x = len("hello") | No useful result to store |
| Python keyword | def | def (same keyword!) |
In Python, both functions and procedures are created with def. Python does not have a separate keyword for procedures. However, in the exam, if a subroutine does not return a value, you should call it a procedure. If it does return a value, call it a function.
# This is a PROCEDURE - it does something but returns nothing
def display_welcome(name):
print(f"Welcome, {name}!")
print("Enjoy your visit.")
# This is a FUNCTION - it returns a value
def calculate_area(length, width):
return length * width
# Procedure - just displays output
display_welcome("Priya")
# Function - we can store and use the result
area = calculate_area(5, 3)
print(f"The area is {area} square units")
Both functions and procedures are types of subroutine (also called subprogram). A subroutine is simply a named block of code that can be called from elsewhere in the program. In the GCSE mark scheme, “subroutine” is the umbrella term, and “function” and “procedure” are the two specific types.
Why functions matter
- Reusability — Write code once, use it as many times as you need
- Readability — A well-named function makes your program easier to understand
- Organisation — Break a big problem into smaller, manageable pieces
- Testing — Smaller blocks of code are easier to check and fix
- Decomposition — This is a key computational thinking skill tested in your GCSE
print(), input(), len(), range(), type(), int(), str(), float(). But there are over 70 built-in functions in total! Others include abs() (absolute value), round(), sorted(), max(), min(), and sum(). You do not need to memorise them all — but knowing they exist will save you writing code from scratch.
NameError. Always put your function definitions at the top of your program.
A very common mistake is to write a function with def but then forget to actually call it. Just defining a function does not run the code inside it — you must call it by writing the function name followed by parentheses, e.g. greet().
# This does NOTHING visible - the function is defined but never called
def say_goodbye():
print("Goodbye!")
# Uncomment the line below to actually run the function:
# say_goodbye()
Scope — where variables live
Variables created inside a function only exist inside that function. This is called local scope. Variables created outside any function are in the global scope and can be seen everywhere.
def my_function():
secret = "I only exist inside the function"
print(secret)
my_function()
# This next line will cause an error - try it!
# print(secret)
Here is a more detailed example showing how local and global scope interact:
# Global variable - accessible everywhere
school_name = "Greenfield Academy"
def print_student_info(student):
# Local variable - only exists inside this function
message = f"{student} attends {school_name}"
print(message)
print_student_info("Amara")
print_student_info("James")
# We can access school_name here (it is global)
print(f"School: {school_name}")
# But we CANNOT access 'message' here (it is local)
# Uncomment the next line to see the error:
# print(message)
Common Mistakes
Watch out for these pitfalls. Every one of them trips up beginners (and even experienced programmers sometimes!):
| Mistake | What goes wrong | How to fix it |
|---|---|---|
| Defining but never calling | The function exists but the code inside it never runs. | Add a function call: my_function() |
| Calling before defining | NameError: name 'my_func' is not defined | Move the function definition above the call. |
Confusing return with print | You try to store the result but get None. | Use return inside the function instead of print. |
| Wrong number of arguments | TypeError: greet() takes 1 positional argument but 2 were given | Check how many parameters the function expects and pass exactly that many arguments. |
| Indentation errors in the body | IndentationError: expected an indented block | Everything inside the function must be indented by exactly one level (4 spaces is standard). |
| Accessing a local variable outside the function | NameError: name 'x' is not defined | Either return the value and store it, or define the variable outside the function. |
Words You Need to Know
These terms come up frequently in GCSE exams. Make sure you can define each one confidently.
| Term | Definition |
|---|---|
| Function | A named block of reusable code that returns a value. |
| Procedure | A named block of reusable code that performs an action but does not return a value. |
| Subroutine / Subprogram | A general term for any named block of code (covers both functions and procedures). |
| Define | To create a function using the def keyword. This tells Python what the function should do. |
| Call | To run (execute) a function by writing its name followed by parentheses, e.g. greet(). |
| Parameter | A variable in the function definition that acts as a placeholder for data. E.g. name in def greet(name): |
| Argument | The actual value passed to a function when it is called. E.g. "Alice" in greet("Alice") |
| Return Value | The value that a function sends back to the code that called it, using the return keyword. |
| Local Variable | A variable created inside a function. It can only be used within that function. |
| Global Variable | A variable created outside any function. It can be accessed from anywhere in the program. |
| Scope | The area of a program where a variable is accessible. Local scope = inside a function; global scope = everywhere. |
| Built-in Function | A function that comes with Python and is always available, like print(), len(), and input(). |
| User-Defined Function | A function that you write yourself using def. |
| Decomposition | Breaking a large problem down into smaller, more manageable sub-problems — often implemented as separate functions. |
Functions in the Real World
Functions are not just a school exercise — they are the foundation of how professional software is built. Here is how they are used in the real world:
Libraries and Modules
Python’s power comes from thousands of pre-built functions organised into libraries (also called modules). Instead of writing everything from scratch, you can import a library and use the functions someone else has already written and tested.
import random
import math
# random.randint() - someone else wrote this function for us!
dice_roll = random.randint(1, 6)
print(f"You rolled a {dice_roll}")
# math.sqrt() - a pre-built function for square roots
result = math.sqrt(144)
print(f"The square root of 144 is {result}")
# math.pi - a pre-defined constant
circumference = 2 * math.pi * 5
print(f"Circumference of a circle with radius 5: {circumference:.2f}")
APIs — Functions that talk to the internet
An API (Application Programming Interface) is essentially a set of functions that lets your program communicate with other services. When an app shows you the weather forecast, it is calling a function that fetches data from a weather service. When you post on social media, the app calls functions in the platform’s API. The world of software runs on functions talking to other functions!
Testing — Functions make code testable
Because each function does one specific job, you can test each function independently. Professional developers write “unit tests” — small checks that make sure each function works correctly. If a function is well-written, you can test it by giving it known inputs and checking the outputs, without worrying about the rest of the program.
Team work — Functions enable collaboration
In a professional software team, different developers can work on different functions at the same time. As long as everyone agrees on the function names, parameters, and return values, each team member can write and test their functions independently. The functions are then combined to create the full program. This is only possible because functions have clear inputs and outputs.
Building a Password Strength Checker
Let us work through a complete example step by step. We will write a function that checks how strong a password is — this is the kind of thing you see on websites every day when you create an account.
The Problem
Write a function called check_password_strength that takes a password string and returns a strength rating: "Weak", "Medium", or "Strong". The rules are:
- The password must be at least 8 characters long
- It should contain at least one uppercase letter
- It should contain at least one lowercase letter
- It should contain at least one digit
Scoring: each rule the password passes earns one point. 0–1 points = “Weak”, 2–3 points = “Medium”, 4 points = “Strong”.
Step 1: Plan the logic
Before writing any code, let us plan:
- Take the password as a parameter
- Start a score counter at 0
- Check each rule — if the rule is met, add 1 to the score
- Based on the score, decide the rating
- Return the rating
Step 2: Write the code
For the character checks, we loop through each character and use Python’s built-in string methods: .isupper(), .islower(), and .isdigit().
def check_password_strength(password):
score = 0
# Rule 1: At least 8 characters long
if len(password) >= 8:
score = score + 1
# Rule 2: Contains at least one uppercase letter
has_upper = False
for char in password:
if char.isupper():
has_upper = True
if has_upper:
score = score + 1
# Rule 3: Contains at least one lowercase letter
has_lower = False
for char in password:
if char.islower():
has_lower = True
if has_lower:
score = score + 1
# Rule 4: Contains at least one digit
has_digit = False
for char in password:
if char.isdigit():
has_digit = True
if has_digit:
score = score + 1
# Decide the rating based on the score
if score <= 1:
return "Weak"
elif score <= 3:
return "Medium"
else:
return "Strong"
# Test with different passwords
test_passwords = ["cat", "password", "Hello123", "MyP4ssw0rd"]
for pwd in test_passwords:
result = check_password_strength(pwd)
print(f"'{pwd}' -> {result}")
Step 3: Trace through an example
Let us trace what happens when we call check_password_strength("Hello123"):
scorestarts at0- Length check:
len("Hello123")is8, which is ≥ 8, soscorebecomes1 - Uppercase check:
"H"is uppercase, sohas_upper = True,scorebecomes2 - Lowercase check:
"e","l","l","o"are lowercase, sohas_lower = True,scorebecomes3 - Digit check:
"1","2","3"are digits, sohas_digit = True,scorebecomes4 - Score is 4, so the function returns
"Strong"
- Add a fifth rule: the password must contain at least one special character (like
!,@,#). Adjust the scoring thresholds accordingly. - Modify the function to return the score as well as the rating, using multiple return values.
Your Turn
Work through these exercises in order. Each one builds on the skills from the last.
Exercise 1 — Personalised Greeting
GuidedWrite a function called personalised_greeting that takes a person's name as a parameter and prints a friendly, personalised greeting.
For example, calling personalised_greeting("Amara") should print something like Hi Amara, welcome to Python!
DEFINE function personalised_greeting that takes name
PRINT a greeting that includes the name
END function
CALL personalised_greeting with a name
# Exercise 1: Personalised Greeting
# Write your function below
def personalised_greeting(name):
# Replace the line below with your greeting
pass
# Test your function
personalised_greeting("Amara")
personalised_greeting("James")
Replace pass with a print() statement. Use an f-string to include the name parameter in the message: print(f"Hi {name}, welcome to Python!")
def personalised_greeting(name):
print(f"Hi {name}, welcome to Python!")
Exercise 2 — Area of a Rectangle
Partially GuidedWrite a function called rectangle_area that takes two parameters — length and width — and returns the area (length × width). Then call it and print the result.
DEFINE function rectangle_area that takes length and width
CALCULATE area as length multiplied by width
RETURN area
END function
STORE the result of calling rectangle_area with two numbers
PRINT the result
# Exercise 2: Area of a Rectangle
# Write your function below
# Test your function
area = rectangle_area(5, 3)
print(f"The area is {area}")
Start with def rectangle_area(length, width): and use return (not print) to send the result back.
Inside the function, calculate area = length * width and then return area. You can also write it in one line: return length * width.
def rectangle_area(length, width):
return length * width
Exercise 3 — Mini Calculator
Open-EndedCreate a mini calculator by writing four separate functions: add, subtract, multiply, and divide. Each function should take two numbers as parameters and return the result.
Then test each function by printing its output. For the divide function, think about what should happen if someone tries to divide by zero.
DEFINE function add that takes a and b
RETURN a plus b
END function
DEFINE function subtract that takes a and b
RETURN a minus b
END function
DEFINE function multiply that takes a and b
RETURN a times b
END function
DEFINE function divide that takes a and b
IF b equals 0
RETURN an error message
ELSE
RETURN a divided by b
END function
CALL each function and PRINT the results
# Exercise 3: Mini Calculator
# Write your four functions below
# Test your functions
print(f"10 + 3 = {add(10, 3)}")
print(f"10 - 3 = {subtract(10, 3)}")
print(f"10 * 3 = {multiply(10, 3)}")
print(f"10 / 3 = {divide(10, 3)}")
print(f"10 / 0 = {divide(10, 0)}")
Each function follows the same pattern. For example: def add(a, b): followed by return a + b. Write all four using the correct operator (+, -, *, /).
For the divide function, use an if statement to check whether b == 0 before dividing. If it is zero, return the string "Error: cannot divide by zero" instead.
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
return "Error: cannot divide by zero"
return a / b
Exercise 4 — Temperature Converter Functions
Partially GuidedWrite two functions:
celsius_to_fahrenheit(celsius)— takes a temperature in Celsius and returns the equivalent in Fahrenheitfahrenheit_to_celsius(fahrenheit)— takes a temperature in Fahrenheit and returns the equivalent in Celsius
The formulae are:
- Fahrenheit = (Celsius × 9/5) + 32
- Celsius = (Fahrenheit − 32) × 5/9
DEFINE function celsius_to_fahrenheit that takes celsius
CALCULATE fahrenheit as (celsius * 9/5) + 32
RETURN fahrenheit
END function
DEFINE function fahrenheit_to_celsius that takes fahrenheit
CALCULATE celsius as (fahrenheit - 32) * 5/9
RETURN celsius
END function
TEST both functions with known values
# Exercise 4: Temperature Converter Functions
# Write your two functions below
# Test your functions
print(f"0°C = {celsius_to_fahrenheit(0)}°F") # Should be 32.0
print(f"100°C = {celsius_to_fahrenheit(100)}°F") # Should be 212.0
print(f"32°F = {fahrenheit_to_celsius(32)}°C") # Should be 0.0
print(f"212°F = {fahrenheit_to_celsius(212)}°C") # Should be 100.0
# Bonus: convert and convert back - should get the original!
original = 25
converted = celsius_to_fahrenheit(original)
back_again = fahrenheit_to_celsius(converted)
print(f"{original}°C -> {converted}°F -> {back_again}°C")
Each function is short — just one calculation and a return. For example: def celsius_to_fahrenheit(celsius): followed by return (celsius * 9/5) + 32.
def celsius_to_fahrenheit(celsius):
return (celsius * 9/5) + 32
def fahrenheit_to_celsius(fahrenheit):
return (fahrenheit - 32) * 5/9
Exercise 5 — Shape Calculator Library
Open-EndedCreate a library of shape calculation functions. Write the following four functions, each one taking the appropriate measurements as parameters and returning the result:
area_of_circle(radius)— returns π × radius² (use3.14159for π, orimport mathand usemath.pi)area_of_triangle(base, height)— returns 0.5 × base × heightperimeter_of_rectangle(length, width)— returns 2 × (length + width)volume_of_cube(side)— returns side³
Test each function and print the results with appropriate labels. Try to round results to 2 decimal places using the round() function.
# Exercise 5: Shape Calculator Library
import math
# Write your four functions below
# Test your functions
print(f"Area of circle (radius 5): {round(area_of_circle(5), 2)}")
print(f"Area of triangle (base 10, height 6): {area_of_triangle(10, 6)}")
print(f"Perimeter of rectangle (4 x 7): {perimeter_of_rectangle(4, 7)}")
print(f"Volume of cube (side 3): {volume_of_cube(3)}")
Each function is a single calculation. For the circle area, use math.pi * radius ** 2. For the cube volume, use side ** 3 (the ** operator means “to the power of”).
def area_of_circle(radius):
return math.pi * radius ** 2
def area_of_triangle(base, height):
return 0.5 * base * height
def perimeter_of_rectangle(length, width):
return 2 * (length + width)
def volume_of_cube(side):
return side ** 3
Check Your Understanding
Before moving on, see if you can answer these questions. Think about each one before revealing the answer.
The def keyword, followed by the function name, parentheses (with any parameters), and a colon. For example: def my_function():
A parameter is the variable name in the function definition (e.g. name in def greet(name):). An argument is the actual value you pass when calling the function (e.g. "Alice" in greet("Alice")).
return and print?return sends a value back to the code that called the function, so you can store it in a variable or use it in further calculations. print simply displays text on the screen but does not give any usable value back — if you try to store the result of print(), you get None.
NameError when calling a function?Two common reasons: (1) you tried to call the function before it was defined — Python reads top to bottom, so the definition must come first; (2) you misspelt the function name when calling it.
Nothing! The code inside the function will never run. Defining a function only tells Python what it should do — you must actually call it (e.g. greet()) for the code to execute.
A function returns a value (using return), whereas a procedure performs an action but does not return a value. In Python, both are created using def, but the distinction matters in GCSE exams. Example of a function: def add(a, b): return a + b. Example of a procedure: def say_hello(): print("Hello").
A default parameter is a parameter that has a pre-set value, so the caller does not have to provide it every time. You set it with = in the definition, e.g. def greet(name, greeting="Hello"):. It is useful when a parameter usually has the same value, but you want the option to change it sometimes.
Summary
Here is everything you have learned in this chapter at a glance:
- A function is a reusable, named block of code. You define it with
defand call it with its name followed by parentheses. - Parameters are the variables listed in the function definition; arguments are the values you pass when calling the function.
- You can set default parameters so that arguments become optional.
returnsends a value back to the caller;printjust displays it on screen.- A function can return multiple values as a tuple.
- Functions can call other functions — this is how we break problems into smaller pieces (decomposition).
- A procedure is a subroutine that does not return a value; a function does return a value. In Python both use
def. - Variables created inside a function have local scope — they cannot be accessed from outside the function.
- Variables created outside any function have global scope — they can be accessed anywhere.
- Following the DRY principle (Don’t Repeat Yourself) means using functions to avoid duplicating code.
Exam-Style Questions
Practise answering these in full sentences, as you would in a GCSE exam. Click to reveal a model answer.
Model answer: A function is a subroutine that returns a value (1 mark) to the part of the program that called it. A procedure is a subroutine that performs an action but does not return a value (1 mark). For example, len("hello") is a function because it returns 5, while print("hello") is a procedure because it displays text but returns None.
Model answer: The scope of a variable refers to the part of the program where that variable can be accessed or used (1 mark). A local variable is declared inside a function and can only be used within that function (1 mark). A global variable is declared outside of any function and can be accessed from anywhere in the program (1 mark).
def add(a, b): print(a + b) and then writes result = add(3, 4). They are surprised that result contains None. Explain why this happens and fix the code. (3 marks)Model answer: The function uses print(), which displays the sum on the screen but does not return a value (1 mark). When a function does not explicitly use return, Python automatically returns None (1 mark). To fix the code, replace print(a + b) with return a + b so that the calculated value is sent back to the caller and stored in result (1 mark).
Fixed code: def add(a, b): return a + b
Extra Resources
Explore functions and subprograms further with these trusted resources:
- BBC Bitesize — Edexcel Computer Science — GCSE revision covering subroutines, functions, and procedures
- W3Schools — Python Functions — Clear tutorials and interactive examples for Python functions
- Python.org — Defining Functions — The official Python tutorial on defining and using functions
- GCSE Topic 6: Subprograms — Functions, procedures, parameters, return values, and scope with interactive code editors
- Program Builder — Build complete programs step by step with drag-and-drop