First exams 2027 · SL & HL

B2.3.4 · Programming constructs

Functions and modularization

Nobody runs a whole school fete cake stall alone, one person takes money, one bags the cakes, one restocks the tray. Splitting a program into named, reusable jobs is the same idea.

Core for SL & HL Typically 3–6 marks · AO3 Command term: construct

Explainer

Every time the cake stall serves a customer, the same three steps happen: work out the price, take the payment, hand over the cake. Writing those three steps out fresh for every single customer would be exhausting and error-prone. Writing them once, giving that block a name, and reusing it for every customer, is what a function is for.

Df

A function is a named, reusable block of code that can take parameters (inputs) and, once it finishes, returns a value. A procedure is the same idea without a return, it might print something or update a variable, but it hands nothing back.

()

Parameters are the placeholder names written in the function's own definition. Arguments are the real values actually supplied when the function is called. One function with parameters can be called many times, with different arguments each time.

Explainer

Why splitting a program into functions helps

Modularization means breaking a program into small, focused, named pieces instead of one long block. Compare working out three customers' totals the two ways:

Repeated inline (no function)
total1 = 4 * 2.50
print("Total:", total1)
total2 = 2 * 2.50
print("Total:", total2)
total3 = 6 * 2.50
print("Total:", total3)
One function, reused
def calc_total(price, quantity):
    return price * quantity

print("Total:", calc_total(2.50, 4))
print("Total:", calc_total(2.50, 2))
print("Total:", calc_total(2.50, 6))

Both versions produce the same three totals. But if the stall ever needs to change how a total is calculated (say, a bulk discount for 5 or more cakes), the function version only needs that logic written once, inside calc_total, instead of hunting down and fixing every repeated copy.

Explainer

A function's parameters and local variables belong only to that call

Global versus local scope is covered in full in B2.1.1, the short version needed here: a function's parameters, and anything the function creates inside its own body, are local to that one call. They exist only while the function is running, and disappear the moment it returns.

!

Reassigning a parameter inside a function does not change the variable that was passed in. The parameter is a local name that starts out holding a copy of whatever value the caller passed. Giving that local name a new value only changes the local copy, the caller's own variable is untouched.

Explainer

The real benefits, applied to the cake stall

Naming a benefit of modularization in the abstract isn't enough to score well, each one has to be tied to what it actually looks like in a specific program.

BenefitWhat it looks like at the cake stall
Reusabilitycalc_total is written once and called for every customer, instead of retyped for each one.
MaintainabilityAdding a bulk discount means editing one function, not searching the whole program for every place a total was calculated.
ReadabilityA line reading calc_total(price, quantity) says what it does; the three lines of arithmetic it hides don't have to be re-read every time.
Team developmentOne person can write and test calc_total while somebody else works on the stock-tracking function, without either one touching the other's code.

Worked example

One function, three different orders

The same calc_total function, called with three different pairs of arguments. This is exactly what "different inputs" means: one reusable block, many outcomes.

calc_total(price, quantity) for three real customers Step 1 of 3

Step 1. A customer buys 4 cupcakes at $2.50 each.

print("Total:", calc_total(2.50, 4))
Total: 10.0

Step 2. The next customer only wants 2. Same function, same body, different arguments.

print("Total:", calc_total(2.50, 2))
Total: 5.0

Step 3. A family buys 6, for a school event. The function's own code never changed between any of these three calls.

print("Total:", calc_total(2.50, 6))
Total: 15.0

Try it yourself

Run the cake stall functions

Change the arguments in any of the three calc_total calls, or add a fourth one of your own, and press Run.

main.py
Loading Python engine…
Output
Press Run to see the output here.

Running in offline fallback mode. The full Python engine couldn't load (blocked school network, or no internet), so this console switched automatically to a small hand-written engine. It supports this page's functions and parameters, but it isn't full Python.

Worked example

Why the discount didn't stick

The stall wants a function that applies a 10% discount to a price. Someone writes it so it reassigns the parameter directly, expecting that to update the caller's variable.

✕

Wrong: reassigning the parameter, with no return.

def apply_discount(price):
    price = price * 0.9    # only changes the LOCAL copy of price

ticket_price = 8.00
apply_discount(ticket_price)
print("Price after discount:", ticket_price)

This prints Price after discount: 8.0, completely unchanged. Inside apply_discount, price is a local name that started out as a copy of 8.00. Reassigning it to 7.20 only changed that local copy, ticket_price back in the caller was never touched.

✓

Right: return the new value, and let the caller reassign its own variable.

def apply_discount(price):
    return price * 0.9

ticket_price = 8.00
ticket_price = apply_discount(ticket_price)
print("Price after discount:", ticket_price)

Now it prints Price after discount: 7.2. The function still never touches the caller's variable directly, but this time the caller takes the returned value and reassigns ticket_price itself.

Check your understanding

A function is defined as def double(n): n = n * 2, with no return. A program then runs x = 5 followed by double(x), then print(x). What gets printed?

Common mistake

Markers reported this pattern on modularity-benefit questions

RecurringQuestions asking for an advantage of modularity are frequently answered with a generic, textbook-sounding line that never actually engages with the program in the question. Naming the right idea in the abstract is not enough, the answer has to say what it looks like in that specific scenario.

✕

Vague, generic: "Using functions makes the code more organized and reusable." True, but it could be pasted onto any program on the exam paper, it says nothing about the cake stall specifically.

✓

Applied to the actual scenario: "Because the total is calculated inside calc_total, adding a bulk discount later only requires changing that one function, rather than finding and editing every place a total was calculated across the program." Names the same benefit, maintainability, but ties it to a concrete change in this specific program.

Revision questions

Past-paper style. Write an answer, then reveal the marking points and mark yourself.

Question 1 · 2 marks

[2]Distinguish between a function and a procedure.

Question 2 · 3 marks

[3]Explain why reassigning a function's parameter inside the function body does not change the value of the variable that was passed in as an argument.

Question 3 · 4 marks

[4]A school fete has three separate stalls, each needing to calculate a total price from a quantity and a unit price. Outline one benefit of writing this as a single shared function rather than three separate blocks of code, applying your answer to this scenario specifically.

Flashcards

Active recall for this statement’s key terms.