SDD6 — Records and Arrays of Records
- I can describe what a record is and explain how it differs from parallel arrays
- I can implement records and arrays of records in Python using the
@dataclassdecorator - I can trace and explain code that reads and updates fields within an array of records using a common index
- I can explain, using an example, why grouping fields into one record avoids the synchronisation risk of parallel arrays
- I can write Python code that declares, populates, and traverses an array of records using a fixed loop
- I can trace through code that reads and updates a field inside a record and correctly state the result
Key vocabulary
record.stock.Grouping related data with records
What is a record?
SDD5 stored related attributes in separate parallel arrays, linked only by a shared index. A record takes a different approach: it groups every field describing one item — a name, a price, a stock level — into a single structured variable. In Python, a record is implemented using the @dataclass decorator, which defines a reusable template — a class — describing a record's field names once. For example, a template Item with fields name, price, and stock can then be used to create Item("Chocolate", 75, 30): one record, a single variable holding three related fields about one item, rather than three separate array elements spread across three different arrays.
Why use records instead of parallel arrays?
Because all of a record's fields live inside one structured variable, they can never become misaligned with each other in the way parallel arrays can. There is no risk of one field's array becoming a different length, or falling out of order relative to another — the fields are inseparably bundled together as a single item. This makes records the safer choice once a problem involves more than one or two attributes per item, which is exactly why records and arrays of records are named separately from parallel arrays in the Higher specification.
Declaring records and arrays of records in Python
Before defining a record template, the dataclass decorator must be imported: from dataclasses import dataclass. A record template is then written as a class, with the @dataclass decorator placed directly above it, and each field listed on its own line with a type hint, for example name: str. Once the template exists, individual records are created by calling the template's name with the field values in order, e.g. Item("Chocolate", 75, 30). An array of records is simply a list containing several such objects — one per item, in order. Every record in the list is built from the same template, so code written to process one record (for example, reading its price field) works consistently for every record in the list.
Traversing an array of records with an index
An array of records is traversed with a fixed loop in exactly the same way as a 1D array or parallel arrays: a single index variable, such as i, is used to select which record to work with — itemRecords[i]. Once a specific record has been selected using the list index, its individual fields are then accessed using dot notation, for example itemRecords[i].price. Both the index and the field name are needed together — the index picks the item, and the field name picks which piece of data about that item to read or change. This same double-lookup pattern is exactly what the standard algorithms in SDD15 rely on when they search or process arrays of records.
Worked examples
from dataclasses import dataclass
@dataclass
class Item:
name: str
price: int
stock: int
tuckShopItem = Item("Chocolate", 75, 30)print(tuckShopItem.name, tuckShopItem.price, tuckShopItem.stock)
Chocolate 75 30 — all three facts about one item, read from a single structured variable rather than three separate arrays.Item template:
itemRecords = [
Item("Crisps", 60, 24),
Item("Juice", 90, 15),
Item("Chocolate", 75, 30),
Item("Water", 50, 40)
]i, to select each record in turn, then dot notation to read its data:
for i in range(len(itemRecords)):
print(itemRecords[i].name, "costs", itemRecords[i].price, "pence, stock:", itemRecords[i].stock)i = 2, itemRecords[2] selects the Chocolate record, and itemRecords[2].price and itemRecords[2].stock read 75 and 30 from inside that same record — compare this with SDD5, where the same two facts came from two entirely separate arrays.itemRecords[2].stock = itemRecords[2].stock - 1Before:
itemRecords[2].stock is 30. After this line runs, it becomes 29 — and no other record is affected, because each record's fields are entirely self-contained.totalStock = 0
for i in range(len(itemRecords)):
totalStock = totalStock + itemRecords[i].stock
print(totalStock)0+24=24, 24+15=39, 39+30=69, 69+40=109.Book template with fields title, author, dueDate:bookRecords = [Book("Wasp Factory", "Iain Banks", "12 Jul"), Book("Room", "Emma Donoghue", "15 Jul")]Write a fixed loop that prints, for every book, a line in the form
<title> by <author> — due <dueDate>.
- Confusing a record with an array of records. A record is one item (one
Itemobject); an array of records is the whole list containing many of them. - Accessing a field with square brackets instead of dot notation.
record["price"]is dictionary-style syntax and does not work on a dataclass — a dataclass field is accessed asrecord.price. - Assuming the type hints (
str,int,float) are enforced by Python. They are a hint for the programmer only — Python does not check them automatically, so you must still type-cast input data correctly yourself before storing it in a record. - Forgetting the double lookup. Both the list index and the field name are required together —
itemRecords[i].price, notitemRecords.price[i]oritemRecords[i]alone. - Reverting to separate parallel arrays out of habit. Once a problem has more than a couple of attributes per item, a record is usually the safer structure — don't default back to SDD5's approach just because it was learned first.
When asked to describe or explain why records are used, always state that a record groups every field for one item into a single structured variable, so those fields can never become out of sync with each other — this is the specific advantage over parallel arrays, and examiners look for that comparison to be made explicitly, not just a description of what a record is. Examiners' own record pseudocode accesses fields by name in exactly this dot-notation style, so fluency with record.fieldName transfers directly to how exam answers are marked.
Task Set A — Core questions
record = Item("Chocolate", 75, 30), where Item has fields name, price, stock in that order, what is the value of record.price?stock field of the third record (index 2) in a list called itemRecords?for i in range(len(itemRecords)): totalStock = totalStock + itemRecords[i].stock starting with totalStock = 0, what is the final value of totalStock?Book record template (using @dataclass) with fields title and author, creates a list of two records, bookRecords, for "Wasp Factory" by "Iain Banks" and "Room" by "Emma Donoghue" — then uses a fixed loop to print each title with its author in the form <title> by <author>.from dataclasses import dataclass
@dataclass
class Book:
title: str
author: str
bookRecords = [
Book("Wasp Factory", "Iain Banks"),
Book("Room", "Emma Donoghue")
]
for i in range(len(bookRecords)):
print(bookRecords[i].title, "by", bookRecords[i].author)
itemRecords[2] = Item("Chocolate", 75, 30), what is the value of itemRecords[2].stock after running itemRecords[2].stock = itemRecords[2].stock - 1?Task Set B — Extension
Book record template has fields title, author, and dueDate. A pupil accidentally writes bookRecords[i].Title (capital T) instead of bookRecords[i].title. Explain what would happen when this code runs, and why this is a particularly easy mistake to make.Higher Computing Science → Software Design & Development → SDD6
Double period. This lesson deliberately reuses SDD5's exact tuck shop scenario and figures (same names, prices, stock, and the 109 total) so pupils can directly compare the two structures on identical data rather than learning a new scenario from scratch.
Suggested timing: 10 min warm-up + vocab · 25 min notes + examples 1–2 (live-code alongside slides, explicitly pointing out where this differs from the SDD5 version on screen) · 15 min example 3 (field update + running total trace) · 10 min "now you try" · 45 min Task Set A · remaining time Task Set B / homework.
Key misconception: pupils often try to access a field with square brackets (itemRecords[2]["price"]) out of habit from arrays generally — reinforce "index first, then dot, then field name" as a fixed rule, and use the record-card visual to physically point at "which card, then which row". Also flag the from dataclasses import dataclass import line explicitly — a missed import is a common early-lesson stumbling block that produces a confusing NameError: name 'dataclass' is not defined on the decorator line.
SQA command words covered: describe, explain, implement, trace.
Extension suggestion: Extension 3 previews SDD15 directly — worth flagging to stronger pupils that this is genuinely rehearsing a skill they will need again, not just an abstract exercise.
Implementation note (5 Jul 2026): this lesson was switched from dictionary-based records to @dataclass-based records after the fact, to match the department's other Higher class and because the SQA's own 2024 QP marking instructions model record field access with dot notation (e.g. allRecipes[n].ingredient), not dictionary brackets. SDD7 and SDD8 were updated to match in the same pass.