SDD7 — Functions and Procedures
- I can describe what a sub-program is, and explain the difference between a function and a procedure
- I can implement functions and procedures in Python, each defined by a name and its arguments
- I can trace and explain code that calls functions and procedures, correctly identifying when a value is returned and when an action is performed
- I can explain, using an example, why a function must return a value but a procedure does not
- I can write Python function and procedure definitions with appropriate names and arguments, and call them correctly
- I can trace through code that mixes function calls and procedure calls, and state the result
itemRecords[2] = Item("Chocolate", 75, 30), what field name would you write after the dot to access the price?Key vocabulary
return in Python) that sends a value back to the code that called it.Organising code with sub-programs
What is a sub-program?
A sub-program is a named, reusable block of code that can be called from elsewhere in a program, rather than being written out repeatedly. Every sub-program is defined by two things: its name, used to call it, and its arguments — the inputs it accepts, listed inside brackets when it is defined and when it is called. The Higher specification splits sub-programs into exactly two kinds: functions and procedures, distinguished by one thing only — whether or not they return a value.
Splitting a program into sub-programs also mirrors the iterative development process from SDD1: each sub-program can be designed, written, and tested as its own small unit, rather than tackling an entire problem as one long, unbroken block of code. A well-chosen sub-program can also be reused — called several times, with different arguments, instead of the same logic being copied and pasted throughout a program. This is exactly the kind of modular structure the mini-projects in SDD19 and SDD20 will ask you to build.
Functions: sub-programs that return a value
A function calculates something and sends the result back to whatever code called it, using a return statement. Because a function produces a value, it can be used directly inside an expression: assigned to a variable, used inside a condition, or passed straight into another calculation, for example stockTotal = calculateTotalStock(itemRecords). A function without a return statement does not actually return anything meaningful — in Python, it silently returns None, even if it performs calculations internally. It is also worth noting that a return statement immediately ends the function — any code written after it inside the same function will never run.
Procedures: sub-programs that perform an action
A procedure performs an action — printing something to the screen, updating a record, saving data — but does not hand back a value for use elsewhere in the program. Procedures are called as a statement on their own line, not used inside an expression: printItemDetails(itemRecords) is a complete, valid line by itself, whereas trying to write total = printItemDetails(itemRecords) + 5 would fail to behave sensibly, since there is no numeric value to add to. Procedures can still take arguments; having inputs is not what separates a function from a procedure. The only distinguishing feature is whether a value is returned.
Naming and calling sub-programs
A sub-program's name should describe what it does clearly and specifically — vague names such as doStuff or process make code harder to read and undermine the "efficient use of coding constructs" criterion tested later at evaluation (SDD18). A good name usually reflects whether the sub-program is a function or a procedure too: calculateTotalStock and isAffordable both suggest a value comes back, while printItemDetails clearly signals an action rather than a result. When a sub-program is called, the arguments given in the call are matched, in order, to the inputs the sub-program was defined to accept. SDD8 covers exactly how this matching works, using the more precise terms formal and actual parameters — this lesson only needs the general idea that a sub-program's name and its arguments together define how it is used.
Function vs procedure — the same tuck shop data, two different jobs
return, so it can be stored in a variable.
def calculateTotalStock(records):
total = 0
for i in range(len(records)):
total = total + records[i].stock
return total
stockTotal = calculateTotalStock(itemRecords)
def printItemDetails(records):
for i in range(len(records)):
print(records[i].name, "costs",
records[i].price, "pence, stock:",
records[i].stock)
printItemDetails(itemRecords)
Worked examples
def calculateTotalStock(records):
total = 0
for i in range(len(records)):
total = total + records[i].stock
return total
stockTotal = calculateTotalStock(itemRecords)
print(stockTotal)return total sends the value back, stockTotal can now be used anywhere else in the program — printed, compared, or passed into another calculation.return statement:
def printItemDetails(records):
for i in range(len(records)):
print(records[i].name, "costs", records[i].price, "pence, stock:", records[i].stock)
printItemDetails(itemRecords)result = printItemDetails(itemRecords), then print(result) — what happens?result is None, because printItemDetails has no return statement — this is exactly what makes it a procedure, not a function.def isAffordable(price, budget):
return price <= budget
if isAffordable(75, 100):
print("Chocolate is affordable")isAffordable returns a Boolean value, it can be used directly inside the if condition — this is only possible because it is a function, not a procedure.price = 75, budget = 100, 75 <= 100 is True, so the condition passes and "Chocolate is affordable" is printed.Item("Chocolate", 75, 30):Write a function called
isInStock that takes one argument, record, and returns True if record.stock is greater than 0, otherwise False.
- Confusing procedures and functions. Trying to use a procedure's "return value" — since it has none, the result is always
Nonein Python. - Forgetting the return statement inside a function. A function without
returndoes not send back its calculated value, even if the calculation itself is correct. - Missing a required argument when calling a sub-program. Python raises a
TypeErrorif a sub-program is called without all the arguments it was defined to accept. - Believing procedures never take arguments. Procedures can and often do take arguments — the function/procedure distinction is entirely about returning a value, not about having inputs.
- Giving a sub-program a vague name such as
doStuff. Sub-programs are "defined by their name and arguments" — an unclear name undermines readability, assessed later at evaluation (SDD18).
When asked to describe or distinguish between a function and a procedure, always state the distinction explicitly: a function returns a value and can be used inside an expression; a procedure performs an action and does not return a value. Simply describing what each one "does" without naming this specific difference will not gain full marks.
Task Set A — Core questions
def calculateTotalStock(records):
total = 0
for i in range(len(records)):
total = total + records[i].stock
return total
Calling calculateTotalStock(itemRecords) on records with stock values 24, 15, 30, and 40 — what value is returned?result = printItemDetails(itemRecords) then print(result), where printItemDetails has no return statement. What happens?def isAffordable(price, budget): return price <= budget, what does isAffordable(90, 80) evaluate to?calculateTotalStock is a function but printItemDetails is a procedure, referring to what each one does with its result. (3 marks)isInStock that takes one argument, record, and returns True if record.stock is greater than 0, otherwise False.def isInStock(record):
return record.stock > 0
return statement anywhere inside it. What value does calling that function actually produce in Python?Task Set B — Extension
Higher Computing Science → Software Design & Development → SDD7
Double period. This lesson continues reusing the SDD5/SDD6 tuck shop scenario and figures (same records, same 109 stock total) — the function/procedure examples are built directly on top of SDD6's itemRecords, so pupils see immediate continuity rather than a new dataset.
Suggested timing: 10 min warm-up + vocab · 20 min notes + compare-panels (live-code both definitions side by side, running each to show the difference in the shell) · 20 min examples 1–3 · 10 min "now you try" · 45 min Task Set A · remaining time Task Set B / homework.
Key misconception: pupils very often try to "use" a procedure's return value, since Python does not stop them from writing result = someProcedure(...) — deliberately demonstrate this live (example 2) and show result printing as None, since seeing the error is more memorable than being told about it.
SQA command words covered: describe, explain, implement, trace, distinguish.
Extension suggestion: Extension 1 deliberately sets up SDD8's formal/actual parameter vocabulary — worth a brief verbal preview at the end of the lesson so the terms aren't completely new next time.
Implementation note (5 Jul 2026): this lesson was switched from dictionary-based records to @dataclass-based records after the fact, to match SDD6's updated implementation (see SDD6 teacher notes for the full rationale). Field access throughout is now dot notation (records[i].stock) rather than bracket/key notation.