Python 3.06: Conditionals HW
Popcorn Hack 1: The Silent Failure
Step 1, before fixing: With amount_requested = 0, the original code printed nothing. There was no error and no warning, so this is a bug, not an error. Python ran it successfully, but the “not a large amount” outcome had no answer, so it silently fell off the end.
Step 2, the fix: one condition has 2 outcomes, so it needs 2 answers. Adding an else gives the missing outcome its answer.
Code Runner Challenge
3.6 Popcorn 1 - Run it first. Then make both outcomes print.
View IPYNB Source
# CODE_RUNNER: 3.6 Popcorn 1 - Run it first. Then make both outcomes print.
amount_requested = 0
# 1 condition -> 2 outcomes -> 2 answers
if amount_requested > 100:
print("This message is asking for a large amount of money.")
else:
# Without this else, an amount of 0 printed nothing at all, which looked the same as "this message is fine."
print("This message is not asking for a large amount of money.")
Actual output:
Code Runner Challenge
3.6 Popcorn 2 - Run it first. Then fix the order.
View IPYNB Source
This message is not asking for a large amount of money.
Popcorn Hack 2: The Chain in the Wrong Order
Step 1, before fixing: With risk_score = 9, the worst possible score, the broken chain told the person:
Code Runner Challenge
3.6 Homework - score a message, then advise on it
View IPYNB Source
Be a little careful, but this is probably fine.
That’s confidently wrong advice for an almost-certain scam.
Step 2, unreachable branches: The elif risk_score >= 6 branch and the elif risk_score >= 9 branch can never run for any score. Any score of 6 or 9 is also >= 3, so the first if catches it, and elif is only asked when everything above it was False. Counting answers doesn’t catch this, since there are still 4 answers for 4 outcomes. You have to check that each branch is reachable.
Step 3, the fix: order the thresholds highest first.
# CODE_RUNNER: 3.6 Popcorn 2 - Run it first. Then fix the order.
risk_score = 9
# 3 thresholds -> 4 outcomes -> 4 answers
# Highest threshold first: elif is only asked when everything above it was False,
# so each branch only catches the scores the branches above it let through.
if risk_score >= 9:
print("Do not reply. This is almost certainly a scam.")
elif risk_score >= 6:
print("This looks risky. Check with someone you trust before replying.")
elif risk_score >= 3:
print("Be a little careful, but this is probably fine.")
else:
print("Nothing suspicious in this message.")
Actual output:
Do not reply. This is almost certainly a scam.
Homework Hack: Build the Trainer’s Scoring Step
The function scores a message with three independent if statements, then reports on the score with an if / elif / else chain. It runs on the starter message, both extreme tests, and the inputs that reach the middle branches.
# CODE_RUNNER: 3.6 Homework - score a message, then advise on it
def check_message(message, amount_requested, known_contact):
risk_score = 0
# Scoring step: a separate if for each signal, because the signals are independent.
# A message can trip any combination of them, so every if is checked, not just the first True one.
# None of these needs an else: when a signal isn't present, the right action is to add nothing,
# and risk_score already holds the correct value. The answer for "no" is "leave the score alone."
# .lower() makes the search catch "Gift Card" and "GIFT CARD" too.
if "gift card" in message.lower():
risk_score = risk_score + 4
if amount_requested > 100:
risk_score = risk_score + 3
if not known_contact:
risk_score = risk_score + 2
print("Message:", message)
print("Risk score:", risk_score)
# Reporting step: this is the decision the user sees, so every score must get an answer.
# 3 thresholds -> 4 outcomes -> 4 answers
# Highest threshold first so no branch is unreachable, and the final else catches every
# remaining score, so nothing from 0 upward falls off the end.
if risk_score >= 9:
print("Advice: Do not reply. This is almost certainly a scam.")
elif risk_score >= 6:
print("Advice: This looks risky. Check with someone you trust before replying.")
elif risk_score >= 3:
print("Advice: Be a little careful, but this is probably fine.")
else:
print("Advice: Nothing suspicious in this message.")
print()
# The starter message: gift cards (+4), $500 (+3), unknown sender (+2) = 9
check_message("URGENT: send gift cards now to unlock your account", 500, False)
# Extreme test 1: a completely clean message from a known contact = 0
check_message("Hi Mom, are we still on for Sunday?", 0, True)
# Extreme test 2: a message that trips every signal, with different capitalization = 9
check_message("Your GIFT CARD reward is waiting, send $250 to claim it", 250, False)
# Reachability: one input set for each of the two middle branches
check_message("Please buy a gift card for the office party", 150, True) # 4 + 3 = 7 -> first elif
check_message("Can you lend me $200 until Friday?", 200, True) # 3 -> second elif
Actual output:
Message: URGENT: send gift cards now to unlock your account
Risk score: 9
Advice: Do not reply. This is almost certainly a scam.
Message: Hi Mom, are we still on for Sunday?
Risk score: 0
Advice: Nothing suspicious in this message.
Message: Your GIFT CARD reward is waiting, send $250 to claim it
Risk score: 9
Advice: Do not reply. This is almost certainly a scam.
Message: Please buy a gift card for the office party
Risk score: 7
Advice: This looks risky. Check with someone you trust before replying.
Message: Can you lend me $200 until Friday?
Risk score: 3
Advice: Be a little careful, but this is probably fine.
Reachability Proof
Signals add 4 (gift card), 3 (over $100), and 2 (unknown contact), so the possible scores are 0, 2, 3, 4, 5, 6, 7, and 9. One input set reaches each of the 4 answers:
| Branch | Scores it catches | Inputs that reach it | Score |
|---|---|---|---|
if risk_score >= 9 |
9 | “URGENT: send gift cards now to unlock your account”, 500, unknown contact | 4 + 3 + 2 = 9 |
elif risk_score >= 6 |
6, 7, 8 | “Please buy a gift card for the office party”, 150, known contact | 4 + 3 = 7 |
elif risk_score >= 3 |
3, 4, 5 | “Can you lend me $200 until Friday?”, 200, known contact | 3 |
else |
0, 1, 2 | “Hi Mom, are we still on for Sunday?”, 0, known contact | 0 |
Every branch has an input that reaches it, so there is no dead code. The output above shows all four answers actually printing.
Extreme Tests
- Clean message (“Hi Mom…”, $0, known contact) scored 0 and printed “Nothing suspicious in this message.”
- All signals (“Your GIFT CARD reward…”, $250, unknown contact) scored 9 and printed “Do not reply.” It also shows that
.lower()catches “GIFT CARD” in capitals.
Both extremes printed a sensible answer, so no input falls off the end.
Stretch: Why if With No else Is Fine Here
In the scoring step, the “no” outcome correctly does nothing because the score just stays the same, but in Example A the “no” outcome was the user’s answer, so leaving it out made the trainer go silent.