All subjects · Computer Science · WCP04 Advanced Practical Programming and Problem-solving

Clean code: consistency, readability and controlling behaviour

Edexcel IAL Computer Science · WCP04 Advanced Practical Programming and Problem-solving

Clean code is code another programmer (or an examiner) can read, trust and change. The specification groups it into consistency, readability and controlling how the program behaves at its edges.

Practise this in the app: instant marking and a fix for every mistake. Free, no email needed to start.

Practise this lesson

Consistency

Follow one style throughout, normally Python's style guide (PEP 8):

Readability

Guard clauses and less nesting

Deeply nested if statements are hard to follow. A guard clause deals with a special or invalid case at the start and returns (or raises) straight away, so the main logic is not indented.

Before:

def ticket_price(age, is_member):
    if age >= 0:
        if is_member:
            if age >= 65:
                return 4
            else:
                return 6
        else:
            return 9
    else:
        return None

After, with guard clauses and named constants:

FULL_PRICE = 9
MEMBER_PRICE = 6
SENIOR_MEMBER_PRICE = 4
SENIOR_AGE = 65

def ticket_price(age, is_member):
    if age < 0:
        raise ValueError("age cannot be negative")
    if not is_member:
        return FULL_PRICE
    if age >= SENIOR_AGE:
        return SENIOR_MEMBER_PRICE
    return MEMBER_PRICE

print(ticket_price(70, True), ticket_price(30, True), ticket_price(30, False))

Output:

4 6 9

Loops can be flattened in the same way, using continue to skip invalid items at the top of the loop body.

Boundaries, exceptions and type conversion

def read_quantity(text):
    try:
        quantity = int(text)
    except ValueError:
        return None
    if quantity < 1 or quantity > 99:
        return None
    return quantity

for raw in ["0", "1", "99", "100", "12.5", "seven"]:
    print(raw, read_quantity(raw))

Output:

0 None
1 1
99 99
100 None
12.5 None
seven None

Worked example

Rewrite this code cleanly: `def f(l):` then `t=0`, `for i in range(len(l)): t=t+l[i]*1.2`, `return t`.

  1. ```python VAT_MULTIPLIER = 1.2 def total_with_vat(prices): # Returns the sum of the prices with VAT added. return sum(price * VAT_MULTIPLIER for price in prices) print(round(total_with_vat([10, 20]), 2)) ```
  2. Output: ``` 36.0 ```

Answer: Meaningful names, a named constant for 1.2, a purpose comment, spaces around operators and a direct loop over the items.

Key idea: PEP 8 consistency (4 spaces, snake_case, CapWords, UPPER_CASE, fixed line length); meaningful names, named constants and purposeful comments; guard clauses to reduce nesting; test boundaries; catch specific exceptions; convert types once, safely.

Check yourself

  1. What does this program print? ```python FULL_PRICE = 9 MEMBER_PRICE = 6 SENIOR_MEMBER_PRICE = 4 SENIOR_AGE = 65 def ticket_price(age, is_member): if age < 0: raise ValueError("age cannot be negative") if not is_member: return FULL_PRICE if age >= SENIOR_AGE: return SENIOR_MEMBER_PRICE return MEMBER_PRICE print(ticket_price(65, True), ticket_price(64, True), ticket_price(65, False)) ```
    Show answer

    4 6 9. 65 is a senior member (>= 65): 4. 64 is a member but not senior: 6. A non-member pays the full price whatever their age: 9. Output: `4 6 9`

  2. Using read_quantity from the lesson, what does this print? ```python def read_quantity(text): try: quantity = int(text) except ValueError: return None if quantity < 1 or quantity > 99: return None return quantity print(read_quantity("1"), read_quantity("100"), read_quantity("3.0")) ```
    Show answer

    1 None None. 1 is the lower boundary and is valid; 100 is just outside the range; '3.0' is not a whole-number string, so int() fails. Output: `1 None None`

  3. Following PEP 8, which name suits a class that represents a diving competition?
    • `DivingCompetition`
    • `diving_competition`
    • `DIVING_COMPETITION`
    • `divingcompetition()`
    Show answer

    `DivingCompetition`. Classes use CapWords; snake_case is for variables and functions; UPPER_CASE for constants.

  4. A field accepts whole numbers from 10 to 50 inclusive. Which set of test values carries out boundary value analysis?
    • 10, 30, 50
    • 1, 25, 100
    • 0, 10, 20, 30, 40, 50
    • 9, 10, 50, 51
    Show answer

    9, 10, 50, 51. Test each boundary and the value just beyond it on the invalid side.

  5. Why is `if len(scores) == NUM_JUDGES:` better than `if len(scores) == 5:`?
    • It runs faster
    • The constant explains the meaning of 5 and lets it be changed in one place
    • Python does not allow numbers in comparisons
    • It stops the list from changing
    Show answer

    The constant explains the meaning of 5 and lets it be changed in one place. Named constants remove magic numbers, improving readability and maintenance.

  6. Which comment is most informative?
    • `# sort the list`
    • `# this is a loop`
    • `# x = x + 1`
    • `# drop highest and lowest so one generous judge cannot skew the score`
    Show answer

    `# drop highest and lowest so one generous judge cannot skew the score`. Good comments explain the reason for code; the others restate what the code already says.

  7. How can a long expression be split over two lines in Python without a syntax error?
    • Indent the second line by 8 spaces with no brackets
    • Put it inside brackets and break the line inside them, or end the first line with a backslash
    • Put a semicolon at the end of the first line
    • Use a # at the end of the first line
    Show answer

    Put it inside brackets and break the line inside them, or end the first line with a backslash. Python continues a line implicitly inside (), [] or {}, or explicitly after \ at the end of the line.

Practise with instant feedback

Sources

Last updated 8 November 2026. Spotted a mistake? Tell us.