You've got is_over_budget telling you whether a campaign overspent — a clean true or false. But your CPO wants three buckets in the weekly report: campaigns that need emergency action, campaigns drifting, and campaigns running well. A bool can't do that. What would you build in Excel?
A nested IF — =IF(A2>1.25*B2, "Critical", IF(A2<1.1*B2, "On Target", "Over Target")). I've written that formula about four hundred times.
Python's if/elif/else is that nested IF, but you read it top to bottom instead of inside out. The first condition that's true wins; everything below it is skipped. The else is your catch-all — the third bucket with no condition to check:
if cpl > 1.25 * target_cpl:
result = "critical"
elif cpl < 1.1 * target_cpl:
result = "on target"
else:
result = "over target"Why does the > 1.25 check come first? If I flip it and test < 1.1 first, do I get different answers?
Yes — and that's the trap. Order matters because Python stops at the first true branch. Test the worst case first so a CPL of 130 against a target of 80 hits "critical" before it even looks at the elif. Flip the order and a value at 1.30× might slide into "on target" if you wrote the condition wrong. Think of it as triage: critical first, then drift, then fine.
So the elif only runs if the if was false. That's why it's safe — by the time we reach elif cpl < 1.1 * target_cpl, we already know cpl isn't in the critical zone.
You just explained short-circuit evaluation better than most engineers do in interviews. The elif inherits the context of every if above it — you get a free "AND not critical" for nothing.
Four hundred nested IFs and it turns out Python was just... letting me read it in order. I feel a little betrayed by spreadsheets right now.
File this: if/elif/else always needs an else when you want a guaranteed return value. Skip it and Python returns None for the case you didn't handle — no error, wrong output, silent bug in a Friday report. The else is your contract that every input gets a label.
def categorize_performance(cpl: float, target_cpl: float) -> str:
if cpl > 1.25 * target_cpl:
result = "critical"
elif cpl < 1.1 * target_cpl:
result = "on target"
else:
result = "over target"
print(f"CPL {cpl} vs target {target_cpl} → {result}")
return resultPython evaluates conditions top to bottom and stops at the first True branch.
| Clause | Runs when |
|---|---|
if | condition is True |
elif | all above were False, this is True |
else | all above were False — guaranteed catch-all |
Order is logic. Put the most exclusive condition first (critical > 1.25×), then progressively looser ones. Each elif silently inherits "AND none of the above."
Omitting else when every input must produce a value:
# Bug: returns None when cpl is between 1.1× and 1.25×
if cpl > 1.25 * target:
return "critical"
elif cpl < 1.1 * target:
return "on target"
# Missing else — silent NoneYou've got is_over_budget telling you whether a campaign overspent — a clean true or false. But your CPO wants three buckets in the weekly report: campaigns that need emergency action, campaigns drifting, and campaigns running well. A bool can't do that. What would you build in Excel?
A nested IF — =IF(A2>1.25*B2, "Critical", IF(A2<1.1*B2, "On Target", "Over Target")). I've written that formula about four hundred times.
Python's if/elif/else is that nested IF, but you read it top to bottom instead of inside out. The first condition that's true wins; everything below it is skipped. The else is your catch-all — the third bucket with no condition to check:
if cpl > 1.25 * target_cpl:
result = "critical"
elif cpl < 1.1 * target_cpl:
result = "on target"
else:
result = "over target"Why does the > 1.25 check come first? If I flip it and test < 1.1 first, do I get different answers?
Yes — and that's the trap. Order matters because Python stops at the first true branch. Test the worst case first so a CPL of 130 against a target of 80 hits "critical" before it even looks at the elif. Flip the order and a value at 1.30× might slide into "on target" if you wrote the condition wrong. Think of it as triage: critical first, then drift, then fine.
So the elif only runs if the if was false. That's why it's safe — by the time we reach elif cpl < 1.1 * target_cpl, we already know cpl isn't in the critical zone.
You just explained short-circuit evaluation better than most engineers do in interviews. The elif inherits the context of every if above it — you get a free "AND not critical" for nothing.
Four hundred nested IFs and it turns out Python was just... letting me read it in order. I feel a little betrayed by spreadsheets right now.
File this: if/elif/else always needs an else when you want a guaranteed return value. Skip it and Python returns None for the case you didn't handle — no error, wrong output, silent bug in a Friday report. The else is your contract that every input gets a label.
def categorize_performance(cpl: float, target_cpl: float) -> str:
if cpl > 1.25 * target_cpl:
result = "critical"
elif cpl < 1.1 * target_cpl:
result = "on target"
else:
result = "over target"
print(f"CPL {cpl} vs target {target_cpl} → {result}")
return resultPython evaluates conditions top to bottom and stops at the first True branch.
| Clause | Runs when |
|---|---|
if | condition is True |
elif | all above were False, this is True |
else | all above were False — guaranteed catch-all |
Order is logic. Put the most exclusive condition first (critical > 1.25×), then progressively looser ones. Each elif silently inherits "AND none of the above."
Omitting else when every input must produce a value:
# Bug: returns None when cpl is between 1.1× and 1.25×
if cpl > 1.25 * target:
return "critical"
elif cpl < 1.1 * target:
return "on target"
# Missing else — silent NoneMorgan's performance marketing team flags campaigns by CPL efficiency each week. Write `categorize_performance(cpl, target_cpl)` that returns `"critical"` if CPL exceeds 125% of target, `"on target"` if CPL is below 110% of target, and `"over target"` otherwise — for example, `categorize_performance(110.0, 80.0)` should return `"critical"`.
Tap each step for scaffolded hints.
No blank-editor panic.