Conditionals & Pattern Matching
📖 Concept
Python's conditional statements are straightforward but have some unique features compared to other languages. Python uses indentation (not braces) to define blocks, and supports structural pattern matching (match-case) since Python 3.10.
Basic if/elif/else:
Python uses elif instead of else if. There's no switch statement in Python before 3.10 — use if/elif chains or dictionary dispatch instead.
Ternary (conditional) expression:
result = value_if_true if condition else value_if_false
This is Python's version of condition ? a : b from C/JavaScript.
Structural Pattern Matching (Python 3.10+):
The match/case statement is NOT just a switch — it's a powerful pattern matching system that can destructure data, match types, apply guards, and bind variables. It's similar to pattern matching in Rust or Scala.
Key patterns:
- Literal patterns: match exact values (
case 200:) - Capture patterns: bind to a variable (
case x:) - Wildcard pattern: match anything (
case _:) - Sequence patterns: destructure lists/tuples (
case [x, y]:) - Mapping patterns: destructure dicts (
case {"key": value}:) - Class patterns: match object attributes (
case Point(x=0, y=y):) - OR patterns: match alternatives (
case 200 | 201:) - Guard clauses: add conditions (
case x if x > 0:)
💻 Code Example
1# ============================================================2# Basic conditionals3# ============================================================4age = 2556if age < 13:7 category = "child"8elif age < 18:9 category = "teenager"10elif age < 65:11 category = "adult"12else:13 category = "senior"1415print(f"{age} years old → {category}")1617# ============================================================18# Ternary expression19# ============================================================20x = 1021result = "even" if x % 2 == 0 else "odd"22print(f"{x} is {result}")2324# Nested ternary (avoid in production — hard to read)25grade = 8526letter = "A" if grade >= 90 else "B" if grade >= 80 else "C" if grade >= 70 else "F"27print(f"Grade: {letter}")2829# ============================================================30# Truthiness in conditionals31# ============================================================32# Python evaluates these as False:33# False, None, 0, 0.0, "", [], {}, set(), ()3435items = []36if not items:37 print("List is empty") # Pythonic way to check emptiness3839# BAD: if len(items) == 0:40# GOOD: if not items:4142name = ""43display = name or "Anonymous" # Short-circuit default4445# ============================================================46# Structural Pattern Matching (Python 3.10+)47# ============================================================4849# Basic value matching50def http_status(status):51 match status:52 case 200:53 return "OK"54 case 301:55 return "Moved Permanently"56 case 404:57 return "Not Found"58 case 500:59 return "Internal Server Error"60 case _:61 return f"Unknown status: {status}"6263print(http_status(200)) # "OK"64print(http_status(418)) # "Unknown status: 418"6566# OR patterns67def classify_status(status):68 match status:69 case 200 | 201 | 202:70 return "Success"71 case 301 | 302 | 307:72 return "Redirect"73 case 400 | 401 | 403 | 404:74 return "Client Error"75 case 500 | 502 | 503:76 return "Server Error"77 case _:78 return "Unknown"7980# Sequence patterns (destructuring)81def process_command(command):82 match command.split():83 case ["quit"]:84 return "Quitting..."85 case ["go", direction]:86 return f"Going {direction}"87 case ["get", item, "from", location]:88 return f"Getting {item} from {location}"89 case ["drop", *items]:90 return f"Dropping: {', '.join(items)}"91 case _:92 return f"Unknown command: {command}"9394print(process_command("go north")) # Going north95print(process_command("get sword from chest")) # Getting sword from chest96print(process_command("drop apple banana")) # Dropping: apple, banana9798# Mapping patterns (dict destructuring)99def process_event(event):100 match event:101 case {"type": "click", "x": x, "y": y}:102 return f"Click at ({x}, {y})"103 case {"type": "keypress", "key": key}:104 return f"Key pressed: {key}"105 case {"type": "scroll", "direction": "up" | "down" as dir}:106 return f"Scrolling {dir}"107 case _:108 return "Unknown event"109110print(process_event({"type": "click", "x": 100, "y": 200}))111print(process_event({"type": "keypress", "key": "Enter"}))112113# Guard clauses (if conditions on patterns)114def classify_point(point):115 match point:116 case (0, 0):117 return "Origin"118 case (x, 0):119 return f"X-axis at {x}"120 case (0, y):121 return f"Y-axis at {y}"122 case (x, y) if x == y:123 return f"On diagonal at ({x}, {y})"124 case (x, y) if x > 0 and y > 0:125 return f"Quadrant I: ({x}, {y})"126 case (x, y):127 return f"Point at ({x}, {y})"128129print(classify_point((0, 0))) # Origin130print(classify_point((5, 5))) # On diagonal at (5, 5)131print(classify_point((3, 4))) # Quadrant I: (3, 4)132133# ============================================================134# Dictionary dispatch pattern (alternative to if/elif chains)135# ============================================================136def add(a, b): return a + b137def sub(a, b): return a - b138def mul(a, b): return a * b139def div(a, b): return a / b if b != 0 else "Error: division by zero"140141operations = {142 "+": add,143 "-": sub,144 "*": mul,145 "/": div,146}147148op = "+"149result = operations.get(op, lambda a, b: "Unknown op")(10, 3)150print(f"10 {op} 3 = {result}") # 10 + 3 = 13
🏋️ Practice Exercise
Exercises:
Write a function
classify_bmi(bmi)that returns "underweight", "normal", "overweight", or "obese" based on BMI ranges. Use both if/elif and match-case versions.Implement a simple command parser using match-case that handles: "help", "quit", "say
", "move ", and unknown commands. Create a
describe_type(value)function that uses match-case with type patterns to describe any Python value (e.g., "integer: 42", "empty list", "dict with 3 keys").Implement a dictionary dispatch calculator that supports +, -, *, /, **, and %. Handle division by zero gracefully.
Write a function that takes a nested dict representing a JSON API response and uses match-case with mapping patterns to extract different fields based on the response type.
Rewrite complex if/elif chains in your own code using match-case. Compare readability.
⚠️ Common Mistakes
Using
if x == True:instead ofif x:. The latter is more Pythonic and works with any truthy value. Only useis Truewhen you specifically need to distinguishTruefrom other truthy values.Forgetting that Python has no switch fallthrough — each
caseblock is independent. There's no need forbreakstatements like in C/Java.Using match-case as a simple switch when if/elif would be clearer for 2-3 conditions. Match-case shines with destructuring, not simple value comparisons.
Not understanding that
case x:in match-case is a capture pattern (binds any value to x), not a comparison to a variablex. To compare to a variable, use a guard:case val if val == x:.Writing empty
ifblocks. Usepassas a placeholder if you intentionally want to do nothing:if condition: pass.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Conditionals & Pattern Matching