1. Lighthouse

Level 5 · Week-over-week change per product

The request

From Thomas Whitaker, Head of Merchandising

“For Monday's buying meeting I need the week-over-week change in units for these five products, as a percent. The string lights only launched this week, so they had no sales last week.”

Your goal

Define pct_change(old, new) that returns (new - old) / old * 100 rounded to 1 decimal, or None when old is 0. Set result to a dictionary mapping each product name in weekly_units to pct_change(last_week, this_week), in the same order.

  • Store a dict in resultnot done yet

Your code

Python

Loading the editor…

    ResultPress Run to see yours

    Mote checks your result

    Press Run. Each row that matches the goal becomes a firefly in your lantern.

    The lesson

    Percent change, the formula

    Percent change compares a new value with an old one, relative to the old one:

    (46 - 40) / 40 * 100      # 15.0   Dutch oven: up 15%
    (102 - 120) / 120 * 100   # -15.0  pillow: down 15%
    (41 - 32) / 32 * 100      # 28.125 vase: up 28.1% after rounding

    The old value is always the denominator. That is what makes “up 15%” mean “15% more than last week”. Divide by the new value and you get a different, wrong number: the pillow would show -17.6%.

    A guard clause for the zero case

    The string lights sold nothing last week. (9 - 0) / 0 raises ZeroDivisionError, and even if it didn’t, there is no meaningful percentage growth from zero. The honest answer is “not defined”, which in Python is None.

    def pct_change(old, new):
        if old == 0:
            return None
        return round((new - old) / old * 100, 1)

    The first if is a guard clause: it handles the special case and leaves the function early with return. The main calculation below it then never has to worry about a zero. Writing the special case first keeps functions flat and readable, without an else wrapped around the main logic.

    Returning None rather than 0 matters. Zero percent means “the same as last week”, which is what the desk lamp did (15 units both weeks). The string lights did something quite different, and the report should show that as a gap, not as “no change”.

    Applying the function to every row

    With the function written once, the loop only unpacks each tuple and stores the answer:

    result = {}
    for name, last_week, this_week in weekly_units:
        result[name] = pct_change(last_week, this_week)

    Dictionaries keep the order in which keys were added, so the result lists the products in the same order as the input. Because the logic lives in one function, next week’s report (or a year-over-year version) reuses it unchanged, and a fix to the zero case only has to happen once.

    Common mistakes

    • Dividing by the new value instead of the old one.
    • Returning 0 or 100 for a zero base. Both look like real numbers in a report and both are wrong.
    • Rounding before multiplying by 100: round((new - old) / old, 1) * 100 turns 28.125% into 30.0%.
    • Forgetting return. A function without it returns None for every product.

    Pick what may run on this site. You can change this any time from "Cookie settings" at the bottom of every page.