Software Engineering › How to answer › Python questions
How to answer Python questions
Python questions are marked on whether the code runs and meets every requirement. The online exam has a Python box. Use the five-step routine, write simple code, and read it back as the computer would. From course notes From NESA material
What it looks like in the real exam
From NESA material 2025 HSC 2025 HSC exam, Q19 (3 marks: string input and selection) and 2025 HSC exam, Q26 (5 marks: a random grid). Sample paper: 2025 NESA sample exam, Q18B (validate a username, 3 marks) and 2025 NESA sample exam, Q21B (a timetable, 5 marks). Familiarisation: 2025 NESA familiarisation exam, Q9B (3 marks) and 2025 NESA familiarisation exam, Q13 (6 marks, a scores table). The question usually gives a description, sometimes a sample output, and you type code into the online Python box (fam Q13 is on the familiarisation exam).
Reasoned No past NESA question in our bank uses Flask routes. Flask appears in the course because the syllabus covers web frameworks (Session management); I include it below as course and general material, verified by running it, but weight your study on the six styles above.
Method (the course’s 5 steps)
- Read the question carefully. Note exactly what to output and in what format. Course step 1
- Analyse the stimulus (a sample run, a table, a grid, a scenario) and list the requirements. Course step 2
- Draft in your head (or in a note): the variables, the loop, the selection, any function. Use the names the question uses. Course step 3
- Write the code in the online Python tool. Type constants at the top, define functions before calling them, then the main program. Run it. Course step 4 From NESA material NESA 2025: “code must execute”; call functions in the main program after defining them.
- Re-read and check against your requirement list: indentation, quotes, colons, output format. Run once more with a normal and an edge input. Course step 5
Syntax you must be able to write from memory
| Task | Python |
|---|---|
| Input and output | name = input('Name? '), print('Hi ' + name), n = int(input()) |
| Selection | if x > 5: / elif x == 5: / else: (colon and indentation) |
| Loops | for i in range(5): (0 to 4), for item in items:, while count < 10: |
| Lists | marks = [3,5,2], marks[0], marks[-1], marks.append(4), len(marks), sum(marks) |
| Strings | s[:3] first three, s[-1] last, s.isupper(), s.isdigit(), s + '123' |
| Dictionaries | d = {'Ava': 80}, d['Ava'], d['Ben'] = 60, for k in d: |
| Functions | def area(w, h): … return w * h; call area(2, 3) |
| Random | import random, random.randint(1, 25) |
| Not equal / equal | !=, == (a single = assigns) |
Worked example 1: strings and selection (2025 HSC Q19)
2025 HSC exam, Q19 · 3 marks
Official marking criteria
- 3 marks: Correct code for the problem.
- 2 marks: Partially correct code that includes a correct selection structure OR password creation.
- 1 mark: Some understanding of the scenario and Python.
NESA sample answer
uName = input('What is your username?')
password = input('What is your password?')
passwordP1 = uName[:3]
passwordP1= passwordP1 + '123'
if passwordP1 == password:
print ('Welcome!')
else:
print ('Incorrect password entered')Notes
From NESA material NESA feedback: process the string inputs; use selection; the code must execute; use correct indentation; call functions after defining them. The slice uName[:3] takes the first three characters. If the sample is not exactly what you type, any code that meets every requirement and runs is fine.
Original practice The sample logic, run with the user “Sam” and password “Sam123” prints “Welcome!”, and with “Sam12” prints “Incorrect password entered”:
uName = input('What is your username? ')
password = input('What is your password? ')
expected = uName[:3] + '123'
if password == expected:
print('Welcome!')
else:
print('Incorrect password entered')Worked example 2: lists, loops and a grid (2025 HSC Q26)
2025 HSC exam, Q26 · 5 marks
Official marking criteria
- 5 marks: Correct Python program that creates a list of unique randomly generated numbers; processes the list correctly; uses selection and looping structures; provides correctly formatted output; uses inbuilt Python functions.
- 4 marks: Substantially correct, most requirements.
- 3 marks: Some requirements.
- 2 marks: One requirement.
- 1 mark: Some understanding of the problem.
NESA sample answer
import random
randList = []
for x in range(15):
nextInt = random.randint(1,25)
while nextInt in randList:
nextInt = random.randint(1,25)
randList.append(nextInt)
pos = 0
while pos < 25:
if pos in randList:
print ("| X", end=" ")
else:
print ("| ", end=" ")
pos = pos + 1
if (pos % 5 == 0):
print("| \n")Notes
Open this question page · some of the NESA wording or answer is an image or is unpublished, as noted
From NESA material NESA feedback: replicate the grid, use the random library, use selection and looping to access the list, check the number of values, use meaningful names and constants, and avoid overly complex nested IF structures.
Reasoned The official sample lists positions 0 to 24 but tests them against 1 to 25 (a possible NESA off-by-one flagged in the bank). Don’t copy it blindly: decide your own index range and check the start and the end.
Original practice My own version (original), run and checked: it always prints 15 X marks in a 5 by 5 grid.
import random
NUMBERS_NEEDED = 15
GRID_SIZE = 5
MAX_NUMBER = GRID_SIZE * GRID_SIZE # 25
chosen = []
while len(chosen) < NUMBERS_NEEDED:
n = random.randint(1, MAX_NUMBER)
if n not in chosen: # keep the numbers unique
chosen.append(n)
for number in range(1, MAX_NUMBER + 1):
if number in chosen:
print('| X ', end='')
else:
print('| ', end='')
if number % GRID_SIZE == 0: # end of a row
print('|')
Constants (GRID_SIZE, NUMBERS_NEEDED) are the “meaningful names and constants” the markers asked for; len(chosen) < NUMBERS_NEEDED is the “check the number of values”.
Worked example 3: validation function (2025 sample Q18b)
2025 NESA sample exam, Q18B · 3 marks
Official marking criteria
- 3 marks: Correct function in Python to check whether a username satisfies the rules.
- 2 marks: Partially correct function.
- 1 mark: Some understanding of the problem and Python.
NESA sample answer
def validate_username(username):
valid = True
# length check
if len(username) < 8:
valid = False
elif (not username[0].isupper()):
valid = False
elif (not username[-2].islower()):
valid = False
elif (not username[-1].isdigit()):
valid = False
return validNotes
Original practice The rule set here is from the NESA sample; the code below follows the same shape and was checked with passing and failing usernames:
def validate_username(username):
valid = True
if len(username) < 8:
valid = False
elif not username[0].isupper():
valid = False
elif not username[-2].islower():
valid = False
elif not username[-1].isdigit():
valid = False
return valid
# main program: call the function AFTER defining it
name = input('Username: ')
print(validate_username(name))
Define the function first, call it in the main program after. Return True or False instead of printing inside, unless the question says to print.
Worked example 4: a 6-mark scores program (2025 familiarisation Q13)
2025 NESA familiarisation exam, Q13 · 6 marks
Official marking criteria
- 6 marks: Substantially correct solution with ALL of: looping correctly; referring to the contents of the data structure correctly; displaying the player's scores and corresponding points as shown; calculating the total points; taking bonus points into account; handling the final round correctly.
- 5 marks: Most features. 3-4: Some features.
- 2 marks: One feature.
- 1 mark: Some understanding.
NESA sample answer
# Input code
scores = [3,5,5,2,1,4,0,1,4,5]
# Display the scores and points
# Header row
print("Round\tScore\tPoints")
totalPoints = 0
# Calculate the points and print
for i in range(len(scores)):
roundNumber = i + 1
score = scores[i]
points = score
# Check if any bonuses apply and NOT the final round
if points == 5 and i != 9:
# Add the points from the next round as bonus points
points += scores[i + 1]
# Check if the final round bonus applies
if points == 5 and i == 9:
# Give the bonus points of 10
points = 10
# Add to the total points tally
totalPoints += points
# Print the results
print(str(roundNumber) + "\t" + str(score) + "\t" + str(points))
print("\nTOTAL POINTS: " + str(totalPoints))Notes
Open this question page · some of the NESA wording or answer is an image or is unpublished, as noted
Reasoned The full stem is not published as text (a comment/print-line issue is flagged in the bank), so rely on the sample answer’s structure: a table printed with a for loop, a points rule inside the loop, a special final-round rule, a running total.
Original practice A working program with the same pattern, run to confirm the total of 42:
scores = [3, 5, 5, 2, 1, 4, 0, 1, 4, 5]
print("Round\tScore\tPoints")
totalPoints = 0
for i in range(len(scores)):
roundNumber = i + 1
score = scores[i]
points = score
# bonus: a 5 in any round except the last adds the NEXT round's score
if points == 5 and i != 9:
points += scores[i + 1]
# final round rule: a 5 in the last round is worth 10
if points == 5 and i == 9:
points = 10
totalPoints += points
print(str(roundNumber) + "\t" + str(score) + "\t" + str(points))
print("\nTOTAL POINTS: " + str(totalPoints))Debugging and reading code
From course notes Reading code: trace it like the pseudocode (variables on paper). Debugging: look for the usual four: = instead of +=, off-by-one in range, wrong indentation, return versus print.
Original practice Example: this function should return the average of the marks. It has two bugs (run: buggy gives 24.33…, fixed gives 60.0).
# BUGGY version (what the question gives you)
def average(marks):
total = 0
for m in marks:
total = m # BUG 1: replaces the total instead of adding
return total / len(marks) + 1 # BUG 2: stray + 1
# FIXED version (what you write)
def average_fixed(marks):
total = 0
for m in marks:
total = total + m
return total / len(marks)
print(average([50, 60, 70]))
print(average_fixed([50, 60, 70]))Python with a database (sqlite3) and parameterised queries
From course notes Use ? placeholders and pass the values separately. Never join user text into the SQL string: that is how SQL injection works. See Python sqlite3 parameterised query and SQL injection.
import sqlite3
conn = sqlite3.connect(":memory:") # an exam program would use a file such as "school.db"
cur = conn.cursor()
cur.execute("""CREATE TABLE Student (
StudentID INTEGER PRIMARY KEY,
Name TEXT NOT NULL,
Mark INTEGER)""")
# CREATE / INSERT: always use ? placeholders, never join user text into the SQL
cur.execute("INSERT INTO Student (Name, Mark) VALUES (?, ?)", ("Sam", 85))
cur.execute("INSERT INTO Student (Name, Mark) VALUES (?, ?)", ("Mia", 72))
conn.commit()
# READ
cur.execute("SELECT Name, Mark FROM Student WHERE Mark >= ?", (80,))
for name, mark in cur.fetchall():
print(name, mark)
# UPDATE and DELETE
cur.execute("UPDATE Student SET Mark = ? WHERE StudentID = ?", (90, 1))
cur.execute("DELETE FROM Student WHERE StudentID = ?", (2,))
conn.commit()
cur.execute("SELECT COUNT(*) FROM Student")
print("rows left:", cur.fetchone()[0])
conn.close()
Original practice Output: Sam 85 then rows left: 1. I also ran an injection test: a joined-string query with ' OR '1'='1 returned every row, the ? version returned none.
Classes, inheritance and overriding
From course notes A class has attributes and methods. A subclass inherits and may override a method. See Inheritance, Method overriding, Python classes and objects.
class Pet:
def __init__(self, name):
self.name = name # attribute set by the constructor
def speak(self):
return self.name + " makes a sound"
class Dog(Pet): # inheritance: Dog IS-A Pet
def speak(self): # method overriding (polymorphism)
return self.name + " barks"
for pet in [Pet("Tom"), Dog("Rex")]:
print(pet.speak())Output: Tom makes a sound and Rex barks.
A Flask login with sessions (course and general)
From course notes Routes map a URL to a function; request.form reads a submitted form; session remembers the user between requests; redirect sends the browser elsewhere. I ran this app with Flask’s test client: a wrong password and an injection attempt are rejected, a right login reaches /dashboard, and after /logout the dashboard redirects to the login.
from flask import Flask, render_template, request, redirect, url_for, session
import sqlite3
app = Flask(__name__)
app.secret_key = "change-me" # signs the session cookie
def check_user(username, password):
conn = sqlite3.connect("school.db")
cur = conn.cursor()
cur.execute("SELECT 1 FROM Users WHERE Username = ? AND Password = ?",
(username, password)) # parameterised: safe from SQL injection
found = cur.fetchone() is not None
conn.close()
return found
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
if check_user(username, password):
session["user"] = username # remember who is logged in
return redirect(url_for("dashboard"))
return render_template("login.html", error="Invalid login")
return render_template("login.html", error=None)
@app.route("/dashboard")
def dashboard():
if "user" not in session: # protect the page
return redirect(url_for("login"))
return render_template("dashboard.html", user=session["user"])
@app.route("/logout")
def logout():
session.clear() # end the session
return redirect(url_for("login"))Common mistakes
- From NESA material “Code must execute.” A typo (
Print, a missing colon) that stops it running loses marks even if the idea is right. - From NESA material Functions defined but never called in the main program.
- From NESA material 2025 Q26: overly complex nested IFs, no constants, wrong keywords or syntax, mishandling list values.
- General advice
input()returns text.int(input())before you compare numbers. - General advice Mixing tabs and spaces. Use 4 spaces for every level.
- General advice Printing the wrong format. Copy the sample output’s spacing, capitals and punctuation exactly.
Time per mark
Derived 5 marks ≈ 9 minutes, 3 marks ≈ 5 minutes, 6 marks ≈ 10.5 minutes at the paper average of 1.75 minutes per mark. General advice Spend 1 to 2 minutes planning, write the simplest working version first, then add the extra requirements.
Practice (5 items, with answers)
Item 1 · original: even numbers
Write Python that prints the even numbers from 2 to 20, each on its own line.
Show the answer
for n in range(2, 21, 2):
print(n)Or for n in range(1, 21): if n % 2 == 0: print(n). Original practice
Item 2 · original: average of a list
Write a function average(marks) that returns the average of a list, then call it with [50, 60, 70] and print the result.
Show the answer
def average(marks):
return sum(marks) / len(marks)
print(average([50, 60, 70]))Prints 60.0 (checked). Original practice
Item 3 · original: find the bugs
This should print the highest mark. Fix it.
marks = [40, 85, 60]
highest = 0
for m in marks
if m > highest
highest == m
print(highest)Show the answer
marks = [40, 85, 60]
highest = 0
for m in marks:
if m > highest:
highest = m
print(highest)Bugs: missing colons after for and if; == compares, = assigns. Prints 85. Original practice
Item 4 · original: a class
Write a class Student with a name and a mark, and a method passed() that returns True if the mark is 50 or more.
Show the answer
class Student:
def __init__(self, name, mark):
self.name = name
self.mark = mark
def passed(self):
return self.mark >= 50
s = Student("Ava", 80)
print(s.passed())Prints True. Original practice
Item 5 · original: safe database query
Write the line that finds the student called name using sqlite3, safely.
Show the answer
cur.execute("SELECT * FROM Student WHERE Name = ?", (name,))Note the one-item tuple needs the trailing comma. Original practice
Terms, flashcards and past questions
Key terms for this page: Python questions · Python functions · Python lists · Python selection (if elif else) · Python for loop and range · Python while loop · Python strings and slicing · Python input and output · Python sqlite3 parameterised query · Python classes and objects · Python random numbers · Python 2D list (grid) · Python validation function pattern · Session management · Inheritance · Method overriding · SQL injection
Flashcards · All key terms · Learn step by step · All past questions · Multiple-choice bank · Mock exam
Past questions used on this page:
← How to answer pseudocode questionsHow to answer SQL questions →