10 Making Decisions
10.1 The Wall
AI generated a chain of if, elif, and else statements. The logic was wrong. It matched the first condition when it should have matched the third. You could not trace through the conditions to find the bug because you did not understand how Python evaluates them. You rearranged the order and broke something else.
Conditional logic is where AI makes its most subtle mistakes. The code runs, the syntax is valid, but the logic is backwards. If you cannot trace through conditions yourself, you will never catch these bugs.
This chapter fixes that.
10.2 Thinking Session
10.2.1 Getting Oriented
Explain Python’s if, elif, and else statements. I want to understand: how does Python decide which branch to take? What happens if multiple conditions are true? And what is the difference between separate if statements and an if/elif chain?
Your AI should explain that elif chains are mutually exclusive, only the first true condition executes. Separate if statements each evaluate independently. This distinction is critical: AI sometimes uses separate if statements when it should use elif, causing multiple branches to fire.
10.2.2 Go Deeper
What are common patterns for conditional logic in Python? I see AI using nested if statements, ternary expressions (x if condition else y), and guard clauses. When is each pattern appropriate?
Guard clauses (early returns for special cases) flatten deeply nested code. Ternary expressions are good for simple either/or assignments but become unreadable when nested. If your AI shows deeply nested if/else, ask it to refactor with guard clauses.
What values are “truthy” and “falsy” in Python? AI writes things like if items: instead of if len(items) > 0:. Are these the same? When does this shorthand cause problems?
10.2.3 Challenge It
What does this code print, and why is it probably a bug?
temperature = 35
if temperature > 30:
print("Hot")
if temperature > 20:
print("Warm")
if temperature > 10:
print("Mild")It prints “Hot”, “Warm”, and “Mild”, all three. The programmer probably wanted only “Hot”. The fix is elif instead of separate if statements. AI generates this bug when it builds conditions incrementally without considering mutual exclusivity.
10.2.4 What You Should Have Learned
if/elif/elsechains are mutually exclusive, only one branch runs- Separate
ifstatements are independent, multiple can run - Guard clauses simplify deeply nested logic
- Truthy/falsy: empty collections, 0, None, “” are all falsy
- Ternary:
x = "yes" if condition else "no"
10.3 The Gap
When you read AI-generated conditional logic, you can now trace the flow. You know whether conditions are mutually exclusive or independent. You can spot when AI should have used elif instead of if, or when a deeply nested block could be flattened with guard clauses.
In the Building Session, you will add categorised responses to your chatbot, different behaviour for greetings, questions, farewells, and default cases.
10.4 Building Session
10.4.1 The Spec
Add response categories to your chatbot:
- Greetings: respond when input starts with “hello”, “hi”, “hey”
- Questions: respond when input contains “?”
- Farewells: respond when input is “bye”, “goodbye”, “quit”
- Default: respond to everything else
- Use an if/elif/else chain, not separate if statements
10.4.2 Prompt It
Update the get_response() function in my chatbot to v1.0. Add categorised responses using an if/elif/else chain:
- Greetings (input starts with “hello”, “hi”, or “hey”): respond warmly
- Questions (input contains “?”): respond helpfully
- Farewells (“bye” or “goodbye”): respond and signal to exit
- Numbers: the existing even/odd check
- Default: a catch-all response
The function should return a tuple: (response_text, should_exit). The main loop checks should_exit to know when to break.
Update the main() function to handle the tuple return.
10.4.3 Read the Code
Your AI will produce something like this:
def get_response(user_input):
"""Categorise input and return (response, should_exit)."""
text = user_input.lower().strip()
# Check categories in priority order
if text in ("bye", "goodbye", "quit"):
return "Goodbye! It was nice chatting.", True
elif text.startswith(("hello", "hi", "hey")):
return "Hello! Great to hear from you.", False
elif "?" in text:
return "Good question! Let me think...", False
else:
try:
number = int(user_input)
parity = "even" if number % 2 == 0 else "odd"
return f"{number} is {parity}.", False
except ValueError:
return f"Interesting. '{user_input}'.", FalseThe elif chain ensures only one category matches. Farewells are checked first, if someone says “bye”, that takes priority over everything else. .startswith() can take a tuple of options. The function returns a tuple (response, should_exit). The boolean flag lets the caller decide what to do.
10.4.4 Stretch It
Add a mood system. Track a mood variable that starts at “neutral”. If the user sends 3 greetings in a row, mood becomes “happy”. If the user sends 3 questions in a row, mood becomes “curious”. Include the mood in the response.
10.5 Your Chatbot So Far
- Ch 1-8: Loop, types, memory, formatting, validation, operators, functions
- Ch 9: Refactored into functions
- Ch 10: Categorised responses with if/elif/else, farewell detection
10.6 Quick Reference
# if/elif/else (mutually exclusive)
if x > 90:
grade = "A"
elif x > 80:
grade = "B"
else:
grade = "C"
# Ternary expression
status = "even" if x % 2 == 0 else "odd"
# Guard clause
def process(data):
if not data:
return None
# main logic here...
# Truthy/falsy checks
if items: # True if list is not empty
if not name: # True if string is empty
if count: # True if not zero