🐍 GCSE Python Revision

AQA Computer Science 8525 — Section 3.2 | Free Interactive Learning

Home About Contact

Free Python Revision for AQA GCSE Computer Science

Interactive exercises, quizzes and guided lessons covering all 18 programming topics in AQA specification 8525, Section 3.2. Designed for students in Years 10 and 11 (ages 14–16).

What Is This Site?

This platform provides free, interactive Python revision for students preparing for the AQA GCSE Computer Science examination (specification 8525, often called AQA GCSE CS or simply the AQA Computer Science exam). Every lesson is mapped directly to Section 3.2 of the official AQA specification, so you can revise with confidence that you are covering exactly what the examiners expect.

Each of the 18 topic units on this site combines several exercise types: multiple-choice questions to test recall, fill-in-the-blank exercises to practise syntax, code-writing challenges where you write Python from scratch with live feedback, and bug-fixing tasks where you identify and correct errors in provided code. As you work through the exercises you earn experience points (XP), unlock achievement badges, and maintain a daily learning streak — all without needing to create an account, because your progress is saved locally in your browser.

The site is completely free. It is designed for students in Years 10 and 11 (typically ages 14–16) studying for their GCSEs, but it is also used by teachers who want to point students to quick practice resources, and by older students who are brushing up on Python fundamentals. Whether you are just starting to learn Python or preparing for your final exams, the structured progression through all 18 topics will help you build both understanding and exam technique.

All written content on this site is original and produced independently. This site is not affiliated with, endorsed by, or connected to AQA in any way. AQA specification references are used solely to help students identify which topics they need to study.

All 18 AQA Section 3.2 Topics

3.2.1/3.2.2Variables, Constants & Data Types
3.2.7Input & Output
3.2.3Arithmetic Operators
3.2.4Selection (if/elif/else)
3.2.4Boolean & Logical Operators
3.2.5For Loops & While Loops
3.2.6String Handling
3.2.8Type Casting
3.2.9Lists & Arrays
3.2.92D Lists
3.2.10Functions & Procedures
3.2.10Parameters & Return Values
3.2.10Variable Scope
3.2.11Reading & Writing Files
3.2.12Exception Handling
3.2.13Testing & Debugging
3.2.14Data Structures
3.2.15Authentication & Security

Variables, Constants and Data Types (3.2.1 / 3.2.2)

Variables and data types are the absolute foundation of every Python program. Before you can write meaningful code, you need to understand how data is stored and labelled in memory, and what kinds of data Python can work with.

A variable is a named location in memory used to store a value that your program can read and change as it runs. Think of it like a labelled box: the label is the variable name, and whatever is inside the box is the value. When you write score = 0, you are telling Python to create a box called score and put the number 0 inside it. Later in the program, you can change what is in the box — for example, score = score + 10 increases the value by ten.

A constant is similar, but its value is intended to remain the same throughout the entire program. The speed of light, the maximum number of login attempts, the price of a subscription — these are all good candidates for constants because changing them by accident would cause serious bugs. Python does not actually prevent you from changing a constant (unlike some other languages), but the convention of writing constants in UPPER_CASE is a clear signal to anyone reading the code. AQA examiners expect students to understand this distinction and to use UPPER_CASE for constants in exam answers.

The four AQA data types

AQA GCSE Computer Science requires knowledge of exactly four data types. You must be able to identify, declare, and use all four:

score = 0              # integer variable — stores a whole number
MAX_LIVES = 3          # integer constant — UPPER_CASE by convention
pi = 3.14159           # real (float) variable
temperature = -12.5    # real (float) — negative is fine
is_logged_in = False   # boolean variable — True or False only
username = "Alice"     # string variable — text in quotes
empty = ""             # empty string — valid, length zero

# Python infers the type automatically — no need to declare it explicitly
print(type(score))         # <class 'int'>
print(type(pi))            # <class 'float'>
print(type(is_logged_in))  # <class 'bool'>
print(type(username))      # <class 'str'>
⚠ Common Mistake Writing booleans incorrectly is extremely common. In Python, True and False must start with a capital letter. Writing true, TRUE, or false will cause a NameError. Similarly, forgetting that constants should be UPPER_CASE will cost marks in AQA exam questions that ask you to "identify the constant" in a block of code.
🎯 AQA Exam Tip AQA questions often ask: "State the data type of the variable X." Make sure you use AQA's preferred terminology: say integer, real, Boolean, and string — not int, float, bool, or str. Also remember that the result of a comparison (e.g. age > 18) is always a Boolean value.
Exam-Style Question A program stores a student's name, their exam percentage, and whether they have passed. State an appropriate variable name and data type for each piece of information.
Model Answer student_name — String, because a name is a sequence of characters.
percentage — Real (float), because percentages can include decimal values such as 73.5.
has_passed — Boolean, because passing is either True or False.

Input and Output (3.2.7)

Almost every useful program needs to communicate with the user — receiving information from them and displaying results back. Python's input() and print() functions are the building blocks of this communication.

print() sends output to the screen (technically to standard output). You can pass it a string directly, a variable, or an expression, and it will display the result followed by a newline. You can print multiple values separated by commas — Python adds a space between them by default. If you want to avoid the automatic newline at the end, you can use the optional end argument: print("Hello", end="").

input() pauses the program and waits for the user to type something and press Enter. The string you pass as an argument is shown as a prompt — the text the user sees before they type. Crucially, input() always returns what the user typed as a string, regardless of what they actually entered. If the user types 42, Python receives the string "42", not the number 42. This is the source of many student mistakes.

Ways to format output

# Basic print — concatenation with +
name = "Bob"
print("Hello, " + name + "!")      # Hello, Bob!

# print() with comma-separated values
age = 17
print("Name:", name, "Age:", age)  # Name: Bob Age: 17

# f-strings (formatted string literals) — the modern, preferred way
print(f"Hello, {name}! You are {age} years old.")  # Hello, Bob! You are 17 years old.

# Expressions inside f-strings
price = 4.99
quantity = 3
print(f"Total: £{price * quantity:.2f}")  # Total: £14.97

# input() — always returns a string
colour = input("What is your favourite colour? ")
print(f"You chose: {colour}")
⚠ Common Mistake Students frequently try to do arithmetic directly on the result of input() without converting it first. For example, total = input("Score: ") + 10 will crash with a TypeError because you cannot add a string and an integer. You must cast first: total = int(input("Score: ")) + 10.
🎯 AQA Exam Tip When writing code in an exam answer, always include a sensible prompt string inside input(). AQA mark schemes often award a mark specifically for the prompt. Also, if a question says "the user inputs a number", remember that you must cast the result to int or float — just using input() alone is not enough.
Exam-Style Question Write a program that asks the user to enter two numbers, then displays their sum, difference, and product. Each result should be labelled clearly.
Model Answer
a = float(input("Enter the first number: "))
b = float(input("Enter the second number: "))
print(f"Sum: {a + b}")
print(f"Difference: {a - b}")
print(f"Product: {a * b}")

Arithmetic Operators (3.2.3)

Python provides a full set of arithmetic operators for mathematical calculations. The standard operators (+, -, *, /) work exactly as you would expect, but two operators in particular — integer division and modulo — are tested heavily in AQA exams and have their own pseudocode equivalents you must know.

Standard arithmetic in Python follows the same precedence rules as in mathematics, often remembered as BIDMAS or BODMAS: Brackets first, then Indices (powers), then Division and Multiplication (left to right), then Addition and Subtraction (left to right). You can always use parentheses to change the order of evaluation.

The full set of arithmetic operators

print(10 + 3)    # 13
print(10 - 3)    # 7
print(10 * 3)    # 30
print(10 / 3)    # 3.3333... (real division — result is a float)
print(10 // 3)   # 3   (integer division — AQA: 10 DIV 3)
print(10 % 3)    # 1   (modulo/remainder — AQA: 10 MOD 3)
print(2 ** 8)    # 256 (2 to the power of 8)

# BIDMAS / BODMAS — precedence matters
print(2 + 3 * 4)    # 14, not 20 — multiplication before addition
print((2 + 3) * 4)  # 20 — brackets override precedence

# Practical use of modulo — check if a number is even or odd
number = int(input("Enter a number: "))
if number % 2 == 0:
    print("Even")
else:
    print("Odd")

The modulo operator has many practical uses beyond simply finding remainders. You can use it to check whether a number is divisible by another (n % 5 == 0 is true whenever n is a multiple of 5), to wrap an index around the end of a list, or to extract individual digits from a number.

⚠ Common Mistake Students confuse / (real division) and // (integer division). Remember: 7 / 2 gives 3.5, while 7 // 2 gives 3. Also be careful with mixed types — 7 / 2 always returns a float even when the answer is a whole number. And remember: in AQA pseudocode, integer division is written as DIV and modulo as MOD.
🎯 AQA Exam Tip Trace-table questions on arithmetic are common. Work through them one line at a time and be particularly careful about order of operations. When a question shows AQA pseudocode using DIV or MOD, remember these translate to // and % in Python.

Selection — if, elif, else (3.2.4)

Selection is one of the three fundamental programming constructs (along with sequence and iteration). It gives a program the ability to make decisions: to do different things depending on the current state of the data. In Python, selection is written using if, elif, and else.

An if statement evaluates a condition — a Boolean expression that is either True or False. If the condition is True, the indented block of code beneath it is executed. If the condition is False, Python skips that block. You can add as many elif (else-if) branches as needed to test additional conditions, and a final else branch will catch anything that did not match any earlier condition.

Indentation is not optional in Python. The indented code block beneath an if statement is what belongs to that condition. AQA examiners mark indentation, so always use consistent 4-space indentation in your exam answers.

grade = int(input("Enter your mark (0–100): "))

if grade >= 90:
    print("Grade 9 — Outstanding!")
elif grade >= 80:
    print("Grade 7–8 — Excellent work")
elif grade >= 70:
    print("Grade 6 — Good")
elif grade >= 60:
    print("Grade 5 — Pass")
elif grade >= 50:
    print("Grade 4 — Standard pass")
else:
    print("Grade 3 or below — Keep practising!")

# Nested if — checking multiple conditions in layers
age = int(input("Enter your age: "))
has_id = input("Do you have ID? (yes/no): ")

if age >= 18:
    if has_id == "yes":
        print("Entry permitted")
    else:
        print("Please show valid ID")
else:
    print("Sorry, you must be 18 or over")

Relational (comparison) operators used in conditions: == (equal to — note two equals signs, not one), != (not equal to), > (greater than), < (less than), >= (greater than or equal to), <= (less than or equal to).

⚠ Common Mistake Using a single equals sign = instead of double equals == inside an if condition is one of the most frequent mistakes. = assigns a value; == compares two values. Writing if grade = 90: is a syntax error; it must be if grade == 90:.
🎯 AQA Exam Tip When writing selection in an exam answer, always check that your conditions are in the right order. If you test if grade >= 50 before if grade >= 90, a student who scored 95 will match the first condition and never reach the Grade 9 branch. Work from the highest or most specific condition down to the least specific.
Exam-Style Question A cinema charges £12 for adults, £7 for children (under 16), and £9 for seniors (65 or over). Write a program that asks for the customer's age and outputs the correct ticket price.
Model Answer
age = int(input("Enter your age: "))
if age < 16:
    price = 7
elif age >= 65:
    price = 9
else:
    price = 12
print(f"Your ticket costs £{price}")

Boolean and Logical Operators (3.2.4)

Logical operators allow you to combine multiple conditions into a single expression. AQA requires knowledge of three logical operators: AND, OR, and NOT. In Python, these are written as lowercase keywords: and, or, not.

age = 17
has_pass = True
is_member = False

# AND — both conditions must be true
if age >= 16 and has_pass:
    print("Boarding allowed")

# OR — either condition is sufficient
if age < 13 or not has_pass:
    print("Entry denied or pass required")

# NOT — negates a condition
if not is_member:
    print("Please sign up for a membership")

# Combining all three
if (age >= 18 or is_member) and has_pass:
    print("Full access granted")

# Truth table example — print all combinations
for a in [True, False]:
    for b in [True, False]:
        print(f"  {a} AND {b} = {a and b}")
🎯 AQA Exam Tip AQA pseudocode uses capitalised AND, OR, NOT, but in Python these are always lowercase. Exam questions often include a truth table and ask you to write the corresponding condition — practise translating truth tables into Python expressions. Also remember that not has higher precedence than and, which has higher precedence than or. Use brackets to make complex conditions readable.

Iteration — For Loops and While Loops (3.2.5)

Iteration — the ability to repeat a block of code — is one of the most powerful features of any programming language. Without loops, you would have to write the same instruction hundreds of times to process a list of data. Python provides two types of loop: for loops (definite iteration) and while loops (indefinite iteration).

For loops — definite iteration

A for loop repeats a block of code a known, fixed number of times, or once for each item in a sequence. The most common pattern uses the range() function to generate a sequence of numbers. range(start, stop, step) produces integers from start up to (but not including) stop, incrementing by step each time.

# Count from 1 to 10 inclusive
for i in range(1, 11):
    print(i)

# Count down from 10 to 1
for i in range(10, 0, -1):
    print(i)
print("Blast off!")

# Iterate over a string — each character in turn
word = "Python"
for char in word:
    print(char)

# Iterate over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit.upper())

# range() details:
# range(5)       → 0, 1, 2, 3, 4
# range(1, 6)    → 1, 2, 3, 4, 5
# range(0, 10, 2) → 0, 2, 4, 6, 8
# range(5, 0, -1) → 5, 4, 3, 2, 1

While loops — indefinite iteration

A while loop keeps repeating as long as its condition remains True. You use it when you do not know in advance how many repetitions will be needed — for example, when validating user input (keep asking until they enter something valid), or when running a game loop (keep playing until the player loses all their lives).

# Keep asking until the user enters a valid password
password = ""
while password != "secret123":
    password = input("Enter the password: ")
print("Access granted")

# Input validation — ensure a positive number is entered
score = -1
while score < 0 or score > 100:
    score = int(input("Enter a score between 0 and 100: "))
print(f"Valid score recorded: {score}")

# Counter-controlled while loop (equivalent to for loop)
count = 1
while count <= 5:
    print(f"Attempt {count}")
    count += 1   # don't forget to update the counter!
⚠ Common Mistake The most dangerous error with while loops is creating an infinite loop — a loop whose condition never becomes False. This happens when you forget to update the variable being tested inside the loop. For example, if you wrote while count <= 5: print(count) without count += 1, the program would print forever. Always make sure something inside a while loop will eventually make the condition false.
🎯 AQA Exam Tip A very common exam question asks you to choose between a for loop and a while loop and justify your answer. The rule of thumb: use for when the number of repetitions is known in advance; use while when you are repeating until a condition is met and the number of repetitions is unknown. AQA also sometimes calls these count-controlled (for) and condition-controlled (while) loops.

String Handling (3.2.6)

String handling is one of the most heavily tested topics in AQA GCSE Computer Science. You need to be comfortable with indexing, slicing, concatenation, and a range of built-in string methods.

A string is a sequence of characters stored in order. Each character in a string has an index (position number), starting at 0 for the first character. This zero-based indexing is very important — students who assume the first character is at position 1 will produce wrong answers in trace questions. Python also supports negative indexing: -1 refers to the last character, -2 the second-to-last, and so on.

Indexing and slicing

text = "Python"
# Indexing — accessing a single character
print(text[0])    # 'P' — first character (index 0)
print(text[1])    # 'y'
print(text[5])    # 'n' — last character
print(text[-1])   # 'n' — last character using negative index
print(text[-2])   # 'o' — second from last

# Slicing — extracting a substring
# text[start:stop] — includes start, excludes stop
print(text[0:3])  # 'Pyt' — characters at positions 0, 1, 2
print(text[2:5])  # 'tho' — characters at positions 2, 3, 4
print(text[2:])   # 'thon' — from position 2 to the end
print(text[:3])   # 'Pyt' — from the start to position 2

String methods

name = "   Alice Smith   "
print(len("Python"))         # 6 — number of characters
print("hello".upper())       # 'HELLO'
print("HELLO".lower())       # 'hello'
print(name.strip())          # 'Alice Smith' — remove whitespace
print("Python".replace("P","J"))  # 'Jython'
print("cat,dog,fish".split(","))  # ['cat', 'dog', 'fish']
print("Hello".find("ll"))    # 2 — index of 'll', or -1 if not found

# Concatenation — joining strings with +
first = "Ada"
last = "Lovelace"
full = first + " " + last
print(full)                  # 'Ada Lovelace'

# Checking substrings
sentence = "The quick brown fox"
print("quick" in sentence)   # True
print("slow"  in sentence)   # False

# Iterating over characters
vowels = 0
for char in "Programming":
    if char.lower() in "aeiou":
        vowels += 1
print(f"Vowel count: {vowels}")
🎯 AQA Exam Tip Slicing questions are common — and the stop index being exclusive catches many students out. To extract characters at positions 2, 3, and 4, you write text[2:5], not text[2:4]. A useful trick: the number of characters in a slice is always stop minus start. Also remember: len() gives the total number of characters, so the last valid index is always len(text) - 1.

Type Casting (3.2.8)

Type casting (also called type conversion) means converting a value from one data type to another. This is necessary because Python is strongly typed — you cannot, for example, add a string and an integer without first converting one of them.

The three casting functions you need to know for AQA are int(), float(), and str(). Each converts its argument to the specified type if possible, and raises an error if the conversion is impossible (for example, int("hello") will cause a ValueError).

# str → int : only works if the string contains a whole number
age_str = "16"
age = int(age_str)            # 16 (integer)
print(age + 1)                # 17

# str → float : the string must contain a valid decimal number
price_str = "3.99"
price = float(price_str)      # 3.99 (float)

# int / float → str : convert a number to a string for concatenation
score = 95
message = "Your score is: " + str(score)
print(message)                # "Your score is: 95"

# Chaining — most common pattern in practice
height = float(input("Enter your height in metres: "))  # e.g. 1.75
weight = float(input("Enter your weight in kg: "))      # e.g. 70
bmi = weight / (height ** 2)
print(f"Your BMI is {bmi:.1f}")

# What CANNOT be cast
# int("hello")   → ValueError: invalid literal for int()
# float("true")  → ValueError
# int(3.9)       → 3  (truncates, does NOT round)
⚠ Common Mistake int(3.9) gives 3, not 4. Casting a float to an int truncates (removes the decimal part without rounding). If you need to round, use the built-in round() function: round(3.9) gives 4. Also, casting an integer to a float always succeeds (float(5)5.0), but casting a float to an integer loses precision.

Lists and Arrays (3.2.9)

A list allows you to store multiple related values in a single variable. Instead of creating student1, student2, student3 as separate variables, you can store them all in a single list. This makes it easy to process large collections of data using loops.

In Python, lists are written using square brackets with items separated by commas: ["apple", "banana", "cherry"]. Items in a list are accessed by their index, starting at 0, just like characters in a string. AQA GCSE Computer Science uses the word array in its pseudocode — in Python, a list serves the same purpose.

scores = [72, 85, 91, 64, 78]

# Accessing items by index
print(scores[0])    # 72 — first item
print(scores[-1])   # 78 — last item
print(len(scores))  # 5 — number of items

# Modifying a list
scores[0] = 75              # update an item
scores.append(88)           # add to the end
scores.insert(2, 60)        # insert 60 at index 2
scores.remove(64)           # remove first occurrence of 64
popped = scores.pop()       # remove and return the last item

# Useful list operations
print(sorted(scores))       # return a sorted copy
print(min(scores))          # smallest value
print(max(scores))          # largest value
print(sum(scores))          # total of all values
print(sum(scores)/len(scores))  # calculate the mean

# Iterating over a list with a for loop
names = ["Alice", "Bob", "Charlie"]
for name in names:
    print(f"Hello, {name}!")

# Iterating with index using range and len
for i in range(len(scores)):
    print(f"Score {i+1}: {scores[i]}")
🎯 AQA Exam Tip When iterating over a list in AQA pseudocode, you will often see FOR i <- 0 TO LEN(myArray) - 1. In Python this translates to for i in range(len(my_list)). Also remember: list indices start at 0, so a list with 5 elements has valid indices 0, 1, 2, 3, 4 — accessing index 5 will cause an IndexError.

2D Lists (3.2.9)

A 2D list (two-dimensional list) is a list where each item is itself a list. This creates a grid or table structure with rows and columns, making it ideal for storing things like seating arrangements, game boards, spreadsheet data, or a class register with multiple attributes per student.

grid = [
    [1, 2, 3],   # row 0
    [4, 5, 6],   # row 1
    [7, 8, 9]    # row 2
]

# Accessing elements: grid[row][column]
print(grid[0][0])  # 1 — top-left (row 0, col 0)
print(grid[1][2])  # 6 — row 1, column 2
print(grid[2][1])  # 8 — bottom-middle

# Modifying a cell
grid[1][1] = 99
print(grid[1])     # [4, 99, 6]

# Iterating over all cells with a nested for loop
for row in grid:
    for cell in row:
        print(cell, end=" ")
    print()        # newline after each row

# 2D list as a class register
register = [
    ["Alice", "Smith", True],
    ["Bob",   "Jones", False],
    ["Carol", "White", True]
]
for student in register:
    status = "Present" if student[2] else "Absent"
    print(f"{student[0]} {student[1]}: {status}")

Functions and Procedures (3.2.10)

Functions and procedures allow you to break a large program into smaller, reusable pieces. Instead of repeating the same block of code in multiple places, you define it once as a function and call it whenever needed. This makes programs shorter, easier to read, and easier to maintain.

In AQA Computer Science, there is an important distinction between a function and a procedure: a function always returns a value using the return statement, whereas a procedure performs an action but does not return anything. In Python, both are created with the def keyword. If a Python function does not include a return statement, it implicitly returns None and is acting like a procedure.

# Procedure — performs an action, returns nothing
def display_welcome(name):
    print(f"Welcome to the quiz, {name}!")
    print("Good luck!")

# Function — calculates and returns a value
def calculate_area(width, height):
    area = width * height
    return area

# Function — can return different values based on input
def letter_grade(mark):
    if mark >= 90:
        return "A*"
    elif mark >= 80:
        return "A"
    elif mark >= 70:
        return "B"
    elif mark >= 60:
        return "C"
    else:
        return "U"

# Calling the subprograms
display_welcome("Alice")          # calls the procedure
area = calculate_area(5, 8)       # stores the returned value
print(f"Area: {area}")            # 40
grade = letter_grade(75)
print(f"Grade: {grade}")          # B

# Functions can call other functions
def describe_grade(mark):
    grade = letter_grade(mark)
    if grade in ["A*", "A"]:
        return f"Grade {grade} — Excellent!"
    else:
        return f"Grade {grade}"
🎯 AQA Exam Tip AQA exam questions sometimes ask you to identify whether a subprogram is a function or a procedure, or to explain why using functions is good practice. Key reasons to give: modularity (the program is broken into manageable parts), reusability (the function can be called multiple times), easier debugging (each part can be tested independently), and readability (the main program reads like a list of high-level steps).

Parameters, Arguments and Return Values (3.2.10)

Parameters are the variable names listed inside the parentheses in the function definition — they are like placeholders that receive the data when the function is called. Arguments are the actual values passed when you call a function. These two terms are often confused — remember: parameters are defined, arguments are passed.

def power(base, exponent):    # base and exponent are PARAMETERS
    result = base ** exponent
    return result

answer = power(2, 10)         # 2 and 10 are ARGUMENTS
print(answer)                 # 1024

# A function can return multiple values as a tuple
def min_max(numbers):
    return min(numbers), max(numbers)

lo, hi = min_max([5, 3, 8, 1, 9, 2])
print(f"Min: {lo}, Max: {hi}")    # Min: 1, Max: 9

# Default parameter values — the argument is optional
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Bob")               # Hello, Bob!
greet("Alice", "Hi there") # Hi there, Alice!

Variable Scope (3.2.10)

Scope determines which parts of the program can "see" and use a variable. A local variable is created inside a function and can only be accessed within that function — it does not exist outside. A global variable is defined outside all functions and can be read from anywhere in the program. However, to modify a global variable from inside a function, you must declare it with the global keyword; otherwise Python creates a new local variable with the same name instead.

total_score = 0    # global variable — exists everywhere

def add_points(points):
    global total_score     # declares we mean the GLOBAL variable
    total_score += points  # modifies the global

def show_score():
    print(f"Total score: {total_score}")  # can READ global without 'global'

add_points(10)
add_points(25)
show_score()           # Total score: 35

# Local variable — only exists inside the function
def calculate_discount(price, pct):
    discount = price * pct / 100   # 'discount' is LOCAL
    return price - discount

final = calculate_discount(100, 20)
# print(discount)  # NameError — 'discount' doesn't exist out here
⚠ Common Mistake Forgetting the global keyword when you intend to modify a global variable is a subtle bug. The code will not crash — Python will silently create a new local variable with the same name, and the global will remain unchanged. This can be very hard to spot. As a general rule, try to avoid modifying global variables from inside functions; it is better practice to pass values in as parameters and return results.

Reading and Writing Files (3.2.11)

Saving data to files is essential for any program that needs to persist information between runs — for example, a game that saves high scores, or a system that stores student records. Python makes file handling straightforward with the built-in open() function.

The recommended way to open a file in Python is using a with statement. The with block automatically closes the file when you leave the block, even if an error occurs. This is safer than opening and closing manually, and is the expected style in AQA exam answers.

File modes

# Writing to a file (creates or overwrites)
with open("scores.txt", "w") as f:
    f.write("Alice: 95\n")
    f.write("Bob: 87\n")
    f.write("Carol: 91\n")

# Appending — add a new score without losing the others
with open("scores.txt", "a") as f:
    f.write("Dave: 78\n")

# Reading the whole file at once
with open("scores.txt", "r") as f:
    contents = f.read()
    print(contents)

# Reading one line at a time (better for large files)
with open("scores.txt", "r") as f:
    for line in f:
        line = line.strip()   # removes \n at the end
        print(line)

# Reading all lines into a list
with open("scores.txt", "r") as f:
    lines = f.readlines()     # each line is an item in the list
    print(f"Number of records: {len(lines)}")
🎯 AQA Exam Tip AQA almost always expects you to use the with open(...) as f: pattern. Also remember that when you read from a file, each line includes a newline character (\n) at the end — use .strip() to remove it before processing. When writing, you must explicitly add \n to move to the next line.

Exception Handling (3.2.12)

Programs do not always run smoothly. A user might type letters when the program expects a number, or a file might not be where the program expects to find it. Without exception handling, these situations cause the program to crash with an unhelpful error message. A try/except block lets you catch errors and respond to them gracefully.

An exception is an error that occurs while the program is running (a runtime error). When an exception occurs inside a try block, Python stops executing the try block and jumps to the matching except block. You can have multiple except clauses to handle different types of exceptions differently.

Common exception types

# Basic try/except
try:
    age = int(input("Enter your age: "))
    print(f"Next year you will be {age + 1}")
except ValueError:
    print("Please enter a whole number, not text.")

# Multiple except clauses
try:
    numerator   = int(input("Numerator: "))
    denominator = int(input("Denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except ValueError:
    print("Please enter integers only.")
except ZeroDivisionError:
    print("Error: cannot divide by zero.")

# Input validation loop using exceptions
while True:
    try:
        score = int(input("Enter a score (0–100): "))
        if score < 0 or score > 100:
            raise ValueError("Score out of range")
        break    # only reaches here if no exception was raised
    except ValueError:
        print("Invalid input. Please enter a whole number between 0 and 100.")

print(f"Score recorded: {score}")
🎯 AQA Exam Tip AQA exam questions often ask you to add exception handling to an existing program, or ask you to identify which type of exception a given piece of code would raise. Know the names and causes of the five common exception types listed above. Also note that AQA may ask you to explain the difference between validation (checking that input meets rules before processing) and exception handling (dealing with errors that occur at runtime).

Testing and Debugging (3.2.13)

Testing is the process of running a program with carefully chosen inputs to verify that it behaves correctly. AQA GCSE Computer Science requires you to understand three categories of test data and three types of programming error.

Three categories of test data

Three types of programming error

# Test table example — testing a grade classifier
# Function to test:
def classify(score):
    if score >= 70:
        return "Distinction"
    elif score >= 50:
        return "Pass"
    else:
        return "Fail"

# Test cases covering normal, boundary, and erroneous data:
test_cases = [
    (75,  "Distinction"),  # normal — well above boundary
    (50,  "Pass"),         # boundary — exactly at Pass threshold
    (70,  "Distinction"),  # boundary — exactly at Distinction threshold
    (69,  "Pass"),         # boundary — just below Distinction
    (49,  "Fail"),         # boundary — just below Pass
    (0,   "Fail"),         # extreme boundary — minimum possible
    (100, "Distinction"),  # extreme boundary — maximum possible
]

for score, expected in test_cases:
    actual = classify(score)
    status = "PASS" if actual == expected else "FAIL"
    print(f"  classify({score}) = {actual} (expected {expected}) [{status}]")
🎯 AQA Exam Tip When a question asks you to create a test plan, always include at least one example of each type: normal, boundary, and erroneous. For boundary testing, include the value exactly at the boundary, one just inside, and one just outside. State the expected output for each test case — AQA usually awards a mark per row of the test table, so a well-structured table with correct expected outputs scores well even if you have a minor error elsewhere.

Data Structures — Dictionaries (3.2.14)

A dictionary is a collection of key–value pairs. Where a list stores values in numbered positions (index 0, 1, 2 …), a dictionary lets you use any immutable value as a key — typically a string or integer that has meaningful descriptive power. You look up a value by providing its key, not a position number.

Dictionaries are defined using curly braces {} with each key–value pair separated by a colon and pairs separated by commas. They are ideal for storing records where each field has a name — a student's details, a product's attributes, or a telephone directory.

student = {
    "name":   "Alice",
    "age":    16,
    "grade":  "A",
    "passed": True
}

# Accessing values by key
print(student["name"])    # "Alice"
print(student["grade"])   # "A"

# Adding and updating
student["school"] = "St Mary's"    # add a new key
student["age"] = 17                # update an existing value

# Removing a key
del student["passed"]

# Check if a key exists
if "name" in student:
    print("Name found:", student["name"])

# Iterating over a dictionary
for key, value in student.items():
    print(f"  {key}: {value}")

# Real-world example — a phone book
contacts = {
    "Alice": "07700 900001",
    "Bob":   "07700 900002",
    "Carol": "07700 900003"
}
name = input("Who do you want to call? ")
if name in contacts:
    print(f"Number: {contacts[name]}")
else:
    print("Contact not found.")
🎯 AQA Exam Tip AQA exam questions sometimes ask you to choose the most appropriate data structure for a given scenario. If you need to store a collection of items and access them by position, use a list. If you need to store named attributes of a single entity, or look up values by a meaningful key, use a dictionary. Be ready to justify your choice with a sentence explaining why that structure suits the problem.

Authentication and Security (3.2.15)

Computer security is an increasingly important topic in GCSE Computer Science. Section 3.2.15 covers how programs protect user accounts and data, including authentication mechanisms, password storage, and common attack types.

Authentication is the process of verifying that someone is who they claim to be. The most common form is username/password authentication, where the user provides credentials that the system checks against its records. A key principle is that passwords should never be stored in plain text — if a database is compromised, plaintext passwords give attackers immediate access to every account, often across multiple sites (since people reuse passwords).

Password hashing

Instead of storing the password itself, a system stores a hash — the output of a one-way mathematical function applied to the password. The same password always produces the same hash, but it is computationally infeasible to work backwards from the hash to the original password. When a user logs in, the system hashes the entered password and compares the hash to the stored one.

import hashlib

def hash_password(password):
    # SHA-256 produces a 64-character hex string
    return hashlib.sha256(password.encode()).hexdigest()

# Registration — store the hash, not the password
stored_hash = hash_password("mySecret123")
print(f"Stored hash: {stored_hash[:20]}...")  # first 20 chars shown

# Login — hash the attempt and compare
attempt = input("Enter password: ")
if hash_password(attempt) == stored_hash:
    print("Login successful")
else:
    print("Incorrect password")

# Simple login system with attempt limiting
MAX_ATTEMPTS = 3
attempts = 0

while attempts < MAX_ATTEMPTS:
    pwd = input("Password: ")
    if hash_password(pwd) == stored_hash:
        print("Access granted")
        break
    attempts += 1
    remaining = MAX_ATTEMPTS - attempts
    if remaining > 0:
        print(f"Wrong password. {remaining} attempts remaining.")
else:
    print("Account locked after too many failed attempts.")

Other security concepts AQA expects

Top AQA Exam Tips for Section 3.2

Having studied all 18 topics, here are the most important exam technique tips based on the most common mark-losing mistakes in AQA Computer Science papers:

  1. Always use int(input(...)), not just input(...), when asking for a number. Forgetting to cast is the single most common error in student code.
  2. Use AQA terminology, not Python terminology, in written answers. Say real, not float. Say integer, not int. Say subprogram or subroutine for functions and procedures collectively.
  3. AQA pseudocode uses DIV and MOD — these map to Python's // and %. Know both.
  4. Indentation is marks — Python code without correct indentation is syntactically wrong. Exam answers that omit or mis-align indentation will lose marks.
  5. String slicing stop index is exclusivetext[2:5] gives characters at positions 2, 3, 4 (not 5).
  6. For trace tables, work through the code one line at a time, updating variables exactly as Python would. Be especially careful with conditions: test them precisely, including boundary cases.
  7. Know when to use for vs while — and be able to justify your choice. Definite iteration (known number of repetitions) → for. Condition-controlled (repeat until something happens) → while.
  8. Test tables need all three types of data — normal, boundary, and erroneous — plus the expected output for each.
  9. Password storage: never plaintext — if an exam question asks how to store passwords securely, the answer is always hashing, not encryption.
  10. Functions return values; procedures do not — state this distinction clearly when asked to explain the difference.

About this site: GCSE Python is a free, independent revision resource for students studying AQA GCSE Computer Science (specification 8525). It is not affiliated with, endorsed by, or in any way connected to AQA. All original content is written and maintained by the site's creator. If you have a question or spot an error, please get in touch. For more information about the site, visit the About page.