Track progress, take quizzes and save notes on this lesson.

Free forever · no card needed

Start free
Intermediate

Subroutines and Scope

2.2.3 Additional programming techniques

Aligned to the OCR J277 specification

Level
Intermediate
Reading time
7 min
Published
11 June 2026
Updated
1 July 2026
On this page
  1. 1.What Is a Subroutine?
  2. 2.Functions — Returning Values
  3. 3.Procedures — Performing Actions
  4. 4.Parameters, Arguments and Passing Arrays
  5. 5.Local and Global Variables
  6. 6.Random Number Generation
  7. 7.Common Exam Mistakes

Key takeaways

  • A function returns a value and its result is used in an expression or assignment; a procedure performs an action and returns nothing.
  • Parameters are the variable names in a subroutine's definition; arguments are the actual values passed in when the subroutine is called.
  • Local variables exist only inside the subroutine where they are declared and are destroyed when that subroutine ends; they cannot be accessed from outside it.
  • Global variables are declared outside all subroutines and can be accessed from anywhere; they should be used sparingly as they make programs harder to debug.
  • random.randint(a, b) returns a random integer where both a and b are inclusive, so randint(1, 6) can return 1, 2, 3, 4, 5, or 6.

What Is a Subroutine?

A subroutine is a named, reusable block of code that performs a specific task. Instead of copying the same code in multiple places, you write it once as a subroutine and call it by name whenever you need it.

OCR J277 requires knowledge of two types of subroutine:

TypeReturns a value?Called withExample use
FunctionYes — produces a resultUsed in an expression or assignmentarea = calculateArea(5, 3)
ProcedureNo — performs an actionCalled as a standalone statementdisplayMenu()

Benefits of using subroutines:

  • Reusability — write once, call many times
  • Maintainability — fix a bug in one place, not everywhere
  • Readability — a well-named subroutine explains what the code does
  • Testing — each subroutine can be tested independently

Procedures perform actions (output, modify state). Functions compute and return a value. A function used without capturing its return value is wasted — you are calling it for the side effect of getting a result but throwing it away.

Functions — Returning Values

A function takes zero or more parameters (input values) and returns exactly one result. The return statement sends the value back to the calling code.

def calculateArea(length, width):
    area = length * width
    return area

result = calculateArea(5, 3)   # result = 15
print(result)                  # 15

Worked example — function to convert Celsius to Fahrenheit:

def celsiusToFahrenheit(celsius):
    fahrenheit = (celsius * 9 / 5) + 32
    return fahrenheit

temp_c = 100
temp_f = celsiusToFahrenheit(temp_c)
print(temp_c, "°C =", temp_f, "°F")   # 100 °C = 212.0 °F

Verify:

A function can be called multiple times with different arguments:

print(celsiusToFahrenheit(0))    # 32.0
print(celsiusToFahrenheit(37))   # 98.6

Procedures — Performing Actions

A procedure performs a task but does not return a value. It may display output, update a variable, write to a file, or modify a list.

def displayGreeting(name):
    print("Hello,", name)
    print("Welcome to the system.")

displayGreeting("Alice")
displayGreeting("Bob")

Worked example — procedure that prints a formatted score report:

def printReport(subject, score):
    if score >= 70:
        grade = "A"
    elif score >= 50:
        grade = "B"
    else:
        grade = "C"
    print(subject + ": " + str(score) + "% — Grade " + grade)

printReport("Maths", 82)           # Maths: 82% — Grade A
printReport("English", 55)         # English: 55% — Grade B
printReport("Science", 44)         # Science: 44% — Grade C

Use a procedure when the subroutine's job is to do something (output, modify). Use a function when the subroutine's job is to compute something and hand the result back.

Parameters, Arguments and Passing Arrays

Parameters are the variable names listed in a subroutine's definition. Arguments are the actual values passed in when the subroutine is called.

def add(a, b):         # a and b are PARAMETERS
    return a + b

result = add(3, 7)     # 3 and 7 are ARGUMENTS

Passing an array to a subroutine:

def findMax(numbers):
    maximum = numbers[0]
    for i in range(1, len(numbers)):
        if numbers[i] > maximum:
            maximum = numbers[i]
    return maximum

scores = [72, 85, 91, 60, 78]
print(findMax(scores))    # 91

Verify: start maximum=72; 85>72→max=85; 91>85→max=91; 60<91→no change; 78<91→no change. Returns 91 ✓

Returning an array from a function:

def doubleAll(numbers):
    result = [0] * len(numbers)
    for i in range(len(numbers)):
        result[i] = numbers[i] * 2
    return result

doubled = doubleAll([1, 2, 3, 4])   # [2, 4, 6, 8]

How much of this have you taken in?

Quiz yourself on this section, free, no card needed.

Test myself

Local and Global Variables

Scope defines which parts of a program can access a variable.

Local variable — declared inside a subroutine. Only accessible within that subroutine. Destroyed when the subroutine ends.

Global variable — declared outside all subroutines. Accessible from anywhere in the program.

A constant is a named value that is assigned once and never changed during the program's execution. Like variables, constants can be local (inside a subroutine) or global (outside all subroutines).

MAX_SCORE = 100    # global constant — accessible everywhere

def grade(score):
    PASS_MARK = 50    # local constant — only accessible inside grade()
    if score >= PASS_MARK:
        return "Pass"
    return "Fail"

print(grade(72))    # Pass
print(grade(43))    # Fail
# print(PASS_MARK)  # NameError — PASS_MARK is local to grade()
total = 0       # global variable

def addToTotal(amount):
    result = amount * 2    # local variable — only exists inside addToTotal
    return result

print(total)     # 0 — accessible globally
# print(result)  # NameError — result does not exist outside addToTotal

Worked example — local vs global:

score = 100      # global

def bonus():
    extra = 50   # local to bonus()
    return score + extra   # can read global score, returns 150

print(bonus())   # 150
print(score)     # 100 — unchanged
# print(extra)   # NameError — extra is local to bonus()

Using local variables and constants is preferred because they cannot accidentally interfere with the rest of the program. Global variables and constants should be used sparingly — they make programs harder to debug.

Random Number Generation

Programs sometimes need unpredictable values — game dice rolls, random quiz questions, shuffled card decks. OCR J277 requires the ability to create and use random numbers.

import random

dice = random.randint(1, 6)    # integer between 1 and 6 inclusive
print(dice)

random.randint(a, b) returns a random integer where . Both bounds are inclusive.

Worked example — simulate 5 dice rolls and count sixes:

import random

sixes = 0
for i in range(5):
    roll = random.randint(1, 6)
    print("Roll:", roll)
    if roll == 6:
        sixes = sixes + 1
print("Sixes rolled:", sixes)

Worked example — generate a random PIN of 4 digits:

import random

pin = ""
for i in range(4):
    pin = pin + str(random.randint(0, 9))
print("PIN:", pin)   # e.g. "3807"

Common Exam Mistakes

1. Confusing functions and procedures

A function returns a value — its result is used in an expression or assigned to a variable. A procedure performs an action and returns nothing. If a subroutine outputs something to the screen, that does not make it a function — returning a value does.

2. Treating local variables as accessible globally

A variable declared inside a subroutine cannot be read or modified from outside it. If you need a value from inside a subroutine, return it (function) or pass the outer variable as a parameter.

3. Confusing parameters and arguments

Parameters are the names in the definition: def add(a, b). Arguments are the values at the call site: add(3, 7). Exam questions may ask which is which.

4. Off-by-one with randint

random.randint(1, 6) can return 1, 2, 3, 4, 5, or 6 — both bounds are included. random.randint(0, 9) gives digits 0–9 inclusive, which is 10 possible values.

MistakeCorrection
Saying displayMenu() is a function because it "does stuff"It returns no value — it is a procedure
Accessing a local variable outside its subroutineReturn the value from the subroutine or pass it as a parameter
random.randint(1, 5) to roll a standard dieUse random.randint(1, 6) — a standard die has faces 1–6

Key terms

Subroutine
A named, reusable block of code that performs a specific task; called by name whenever needed, avoiding code duplication.
Function
A subroutine that returns a value using a return statement; the result is used in an expression or assigned to a variable.
Procedure
A subroutine that performs an action but does not return a value; called as a standalone statement.
Parameter
A variable name listed in a subroutine's definition that receives a value when the subroutine is called.
Argument
The actual value passed to a subroutine at the point of calling, corresponding to a parameter in the definition.
Local variable
A variable declared inside a subroutine; only accessible within that subroutine and destroyed when it ends.
Global variable
A variable declared outside all subroutines; accessible from anywhere in the program.
Scope
The region of a program in which a variable can be accessed; local variables have subroutine scope, global variables have program-wide scope.
Return statement
The statement inside a function that sends a computed value back to the code that called the function.
random.randint(a, b)
A Python function that returns a random integer between a and b inclusive; both bounds can be returned.

Frequently asked questions

A function returns a value that can be used in an expression or stored in a variable. A procedure performs an action (such as printing output) and returns nothing. Printing to the screen does not make a subroutine a function - returning a value does.

Parameters are the variable names listed in a subroutine's definition, for example def add(a, b). Arguments are the actual values passed when the subroutine is called, for example add(3, 7). In this case a and b are parameters; 3 and 7 are arguments.

Global variables can be accessed and changed from anywhere in the program, which makes it harder to trace bugs and understand what a subroutine does. Local variables are preferred because they cannot accidentally interfere with the rest of the program.

Generate revision on any topic you study

Type any topic you're studying and Aicademy generates a complete lesson, quiz, and flashcard set, personalised to your level.

Lessons on anything

Structured, level-matched lessons on any topic you study

Practice quizzes

Find out what you actually know before the exam does

Flashcard sets

Lock in key concepts with instant revision cards

Ask Aica

Stuck on something? Get a clear explanation, any time

Next

Defensive Design

Related lessons

6 min

6 min

Lesson

Arrays and Records

OCR GCSE Computer Science · OCR J277

1 month ago

7 min

Lesson

Defensive Design

OCR GCSE Computer Science · OCR J277

1 month ago

8 min

Lesson

Testing Programs

OCR GCSE Computer Science · OCR J277

1 month ago

Top students don’t revise more. They revise what counts.

Start revising free

Free to start. No card needed.