CSSE1001 Exam Preparation: A Complete Guide
StudyPilot Team
Education Experts
CSSE1001 (Programming in the Large) is the gateway course for almost every computing degree at UQ. It teaches Python from the ground up, but it also teaches the habits that the rest of your degree assumes — reading code, debugging methodically, and writing functions that another human can understand. This guide breaks down what the final exam actually tests, the eight topics that consistently appear on past papers, and a 4-week study plan that you can start today.
What the final actually tests
The CSSE1001 final exam is paper-based for most semesters — you do not have a computer to run code. This single fact changes everything about how you should study. If your only practice is "type code, hit run, see output," you will be unprepared. The exam tests whether you can read and reason about code that has not been run yet.
Four question types appear on almost every past paper, in roughly this proportion:
- Code tracing (~30%) — given a function, predict the output.
- Debugging (~20%) — given broken code, identify the bug and explain how to fix it.
- Write a function (~35%) — given a specification, write a complete Python function from scratch.
- Recursion trace or write (~15%) — a recursive function, often combined with one of the above.
The exact percentages shift each semester. Some semesters drop debugging entirely. Some add a question on classes or file I/O. Always check the current semester's course profile and any sample papers your lecturer publishes — those are more reliable than blog guides like this one. Use this guide for the topics and patterns, and the course profile for the format.
The 8 topics that dominate past papers
These eight topics cover roughly 90% of what past CSSE1001 papers test. Work through them in order — each one builds on the last.
1. Variables, types, and conversions. Watch for integer division (//) versus float division (/) — 7/2 is 3.5 but 7//2 is 3. String concatenation versus addition: "3" + "4" is "34", not 7. Implicit truthiness in conditions: if [] is False, if 0 is False, but if "0" is True. Practice 5–10 short tracing questions until you can predict the type of every expression in your head.
2. Conditionals. Past papers love testing the difference between == and is. == compares values; is compares object identity. So [1, 2] == [1, 2] is True, but [1, 2] is [1, 2] is False. Also watch for chained comparisons like 1 < x < 10 (one expression, not two) and short-circuit evaluation: if x and x[0] > 5 will not crash when x is empty, because the first half is already False.
3. Loops. For loops on lists are easy. The exam variations that catch students are nested loops with break and continue (which loop does each one break?), loops that modify the list they are iterating (almost always a bug), range() boundaries (range(1, 5) is 1, 2, 3, 4 — not 5), and enumerate() when the question asks for index and value together. Practice tracing 3–5 nested loops by hand on paper.
4. Functions and scope. The hidden traps here cost the most marks. Mutable default arguments — def f(x, lst=[]) — reuse the same list across calls, and this is a classic exam trick. Return versus print: print shows output but the function still returns None, so a function with only print cannot be chained. Local versus global scope: assigning to a variable inside a function creates a local one unless you use global, which you almost never should.
5. Lists, dicts, and tuples. The biggest trap is mutable versus immutable. Lists and dicts are mutable, so passing them into a function and modifying them changes the original. Tuples and strings are immutable, so "hello"[0] = "H" is a TypeError. Slicing creates a shallow copy — lst[:] is a different list, but the items inside are the same objects. Know list comprehensions: [x*2 for x in lst if x > 0] is the same as a for-loop with an if filter, and exams will ask you to read one and predict its output.
6. File I/O. Just memorise the with pattern below. Past paper questions on file I/O often combine reading lines, splitting on a delimiter, and accumulating into a dict. Make sure you can do that in one function without help.
with open("file.txt") as f:
for line in f:
line = line.strip()
...7. Recursion. This is the single most-tested topic in CSSE1001 and the single biggest source of lost marks. Every recursive function has two parts: a base case that says when to stop, and a recursive case that says how each step moves closer to the base case. If your base case is wrong, your function recurses forever. If your recursive case does not shrink the input, same problem. Practice both tracing recursion (predict the output, line by line) and writing recursive functions — past papers test both.
8. Classes and OOP. Most students panic when they see a class question, but these are usually the easiest marks on the paper if you have practised them. Know that __init__ is the constructor, self is the instance, an attribute set in __init__ becomes an instance attribute, method calls are self.method() (never just method()), and inheritance uses class Dog(Animal) with super().__init__() inside the child's constructor. Write 3–5 classes by hand on paper before the exam. Typing them is not the same — you need to remember the syntax without an IDE.
The 4 question types you will see
Most CSSE1001 past papers boil down to four question patterns. Recognising the pattern is half the work.
Code tracing. A function is given, sometimes with several calls. Your job is to predict the output without running it. The trick is to be systematic — make a small table on the side of the page with one row per loop iteration, tracking each variable. Updating the table line by line catches bugs that "trace it in your head" misses every time.
Debugging. A function is broken. The bug is usually one of: wrong base case in recursion, off-by-one in a loop, mutable default argument, missing return, or incorrect comparison operator. When you find a bug, the marker wants two things — identify the bug, and explain why it is wrong. "Line 5 has x = x + 1 but should be x += 2" loses marks. Better: "Line 5 increments x by 1, but the function is supposed to count even numbers, so x should increment by 2." Do not rely on an AI tool to find these for you in practice — see why you shouldn't trust AI for exam answers.
Write a function. A spec is given. Write the complete function, including a docstring if the course standard requires one. Read the spec twice before writing anything. Pay attention to parameter types and return type, edge cases mentioned (empty list, negative input), and whether the function should modify the input or return a new value. Always handle the edge cases the spec explicitly mentions, and include the base case if recursion is involved.
Recursion trace. A recursive function is given with a call like f(4). Your job is to write every recursive call and every return value, in order. This is where students who only ever ran their code lose marks — there is no "run it and see." You have to trace it on paper.
Worked example: recursion trace
Here is a recursion trace exactly like one that has appeared on a past paper.
def mystery(n):
if n <= 1:
return 1
return n * mystery(n - 2)What is the output of mystery(7)?
Many students stop at "this is factorial-ish, probably 7!" and move on. The correct approach is to trace it.
mystery(7) = 7 * mystery(5)
mystery(5) = 5 * mystery(3)
mystery(3) = 3 * mystery(1)
mystery(1) = 1 (base case)Now unwind the stack:
mystery(3) = 3 * 1 = 3
mystery(5) = 5 * 3 = 15
mystery(7) = 7 * 15 = 105The answer is 105 — not 5040 (which would be 7!).
Two common mistakes here. First, assuming the pattern is n * mystery(n - 1) and computing 7! = 5040. The recursive call is mystery(n - 2), not mystery(n - 1), so this is the product of odd numbers up to n, not all numbers. Second, getting the base case wrong. The base case n <= 1 covers both n = 1 and n = 0. If you ran mystery(6), the recursion would reach mystery(0) which returns 1, and the answer would be 6 × 4 × 2 × 1 = 48.
Always trace recursion. Never assume the pattern from the function name or shape — read every line.
A 4-week study plan
This plan assumes you start 4 weeks before your final and study about 10 hours a week on CSSE1001.
Week 1 — Diagnostic and gaps. Do one past paper under timed conditions (no IDE, no Python). Identify which of the 8 topics above you cannot solve. Read lecture notes on those topics only — do not start from week 1 of the course.
Week 2 — Targeted practice. For each weak topic, do 10–15 questions from past papers or a question bank. Hand-trace, no Python. The point is to build the mental model of how Python evaluates code, not to test your typing.
Week 3 — Mixed practice and recursion focus. Do a mix of all 8 topics in random order. Spend at least 3 sessions specifically on recursion: trace, write, trace, write. Recursion is where most students lose 5–10 marks on the final.
Week 4 — Mock exams. Two full mock exams, both untimed first time then timed. Save the most recent past paper for the day-before light review. Sleep early the night before — no last-minute cramming.
For the underlying study technique that makes this plan work, see How to Efficiently Use Past Exam Papers. The 4-step framework there is what turns each past paper into a week of focused study.
What to do next
CSSE1001 is hard for the right reason: it is the first course that asks you to think like a computer instead of like a person. The eight topics above are the boundary between students who pass and students who excel. None of them are difficult on their own. They become difficult only when you have not practised them on paper.
If you want a curated set of CSSE1001 past exam questions — tagged by topic, with worked solutions covering the four question types above — that is what StudyPilot's CSSE1001 question bank is built for. Pick the topic you are weakest in (probably recursion), run the 4-step framework, and check back in a week.