The request

From Thomas Whitaker, Head of Merchandising
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
Loading the editor…
Reference solution
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
What Thomas gets, and why
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) * 100turns 28.125% into 30.0%. - Forgetting
return. A function without it returnsNonefor every product.
Lantern lit!
Practised: defreturnnonepercent changedictionaries
- Solved
- No hints
- First run
