Conditional Statements

🔀 Conditional Statements

Python's conditional syntax will feel immediately familiar — same logic as Java and JavaScript, but cleaner. No curly braces, no parentheses required around conditions, and several features (chained comparisons, truthiness, the conditional expression) that have no direct equivalent in Java.

⚡ Coming from Java / JavaScript Four key differences: (1) elif not else if. (2) and / or / not instead of && / || / !. (3) Indentation defines blocks — no curly braces. (4) Python's concept of truthiness is broader — empty lists, 0, None, and empty strings are all falsy, which leads to a more expressive style of condition writing.
🚀 FastAPI relevance — HIGH Conditional logic is everywhere in route handlers. Checking if a requested item exists, validating user permissions, deciding what HTTP status code to return, branching on query parameter values — all of this uses the patterns in this lesson. The conditional expression (ternary) is particularly common in building response objects.

🧱 Core Syntax

Basic structure
if / elif / else
Conditions don't need parentheses. Each block is defined by indentation (4 spaces is the Python standard). elif is short for "else if" — not two separate words as in Java/JS.
if days_left <= 0: print("Expired!") elif days_left <= 3: print("Expiring soon") elif days_left <= 7: print("Use this week") else: print("Plenty of time")
Logical operators
and / or / not
Python uses words, not symbols. and = &&, or = ||, not = !. They work identically in terms of precedence: not first, then and, then or.
if is_vegetarian and not has_gluten: print("Suitable") if is_expired or qty == 0: print("Out of stock") if not pantry: # empty list is falsy print("Nothing in pantry")
Identity & membership
is / in / not in
is checks identity (same object), not equality. in checks membership in any iterable — much cleaner than Java's .contains() or JS's .includes().
# Identity — always use for None if expiry is None: print("No expiry set") # Membership — works on lists, tuples, strings, dicts if "milk" in pantry: print("Milk found") if "nuts" not in allergens: print("Nut-free")
Chained comparisons
a < b < c
Python allows chained comparisons — a feature Java and JavaScript don't have. 0 < x < 10 is genuinely equivalent to x > 0 and x < 10. Reads like mathematics.
# Java: qty > 0 && qty <= 100 # Python: if 0 < qty <= 100: print("Normal stock") if 1 <= days_left <= 3: print("Expiring soon")

💡 Truthiness — Python's Flexible Booleans

In Python, any object can be used in a boolean context. This lets you write natural-sounding conditions like if pantry: instead of if len(pantry) > 0:. Knowing what is falsy is essential — it's a short list.

❌ Falsy — evaluate as False
NonePython's null
Falsethe boolean False
0integer zero
0.0float zero
""empty string
[]empty list
{}empty dict
()empty tuple
set()empty set
✅ Truthy — evaluate as True
Truethe boolean True
1, -1, 42any non-zero number
"hello"any non-empty string
[1, 2]any non-empty list
{"a": 1}any non-empty dict
(1,)any non-empty tuple
{1, 2}any non-empty set
<any object>instances are truthy by default
Truthiness in Practice — the Pythonic Style
Using truthiness directly (rather than explicit comparisons) is considered more idiomatic Python. Both versions work — the truthiness version is preferred.
# Checking an empty list pantry = [] # Java-style (works but not Pythonic) if len(pantry) == 0: print("Empty") # Pythonic — empty list is falsy if not pantry: print("Empty") # Checking a string name = "" if not name: print("Name is missing") # Checking None or empty together description = None if not description: # catches both None AND "" description = "No description provided" # Checking a number is non-zero quantity = 0 if not quantity: print("Out of stock")

💻 Examples in Context

Stock Level Check — Multi-Branch Logic
A realistic example of chained elif branches — categorising an ingredient's status for the meal planner's inventory system.
ingredient = {"name": "milk", "qty": 1, "days_left": 2} name = ingredient["name"] qty = ingredient["qty"] days_left = ingredient["days_left"] # Check expiry first, then quantity if days_left <= 0: status = "🚫 EXPIRED — discard" elif days_left <= 3 and qty > 0: status = "⚠ Use urgently" elif qty == 0: status = "🛒 Out of stock — add to shopping list" elif 1 <= days_left <= 7: status = "✓ Use this week" else: status = "✓ Plenty of time" print(f"{name}: {status}") # → milk: ⚠ Use urgently
Dietary Filter — Combining Conditions
Using and, or, and not to check multiple dietary requirements at once.
recipe = { "name": "Mushroom Risotto", "vegetarian": True, "vegan": False, "gluten_free": True, "allergens": ["dairy"], "prep_mins": 45, } user_is_vegan = False user_is_vegetarian = True user_max_prep = 60 user_allergens = ["nuts"] # Check if suitable for this user diet_ok = ( not user_is_vegan or recipe["vegan"] ) and ( not user_is_vegetarian or recipe["vegetarian"] ) time_ok = recipe["prep_mins"] <= user_max_prep allergen_ok = not any(a in recipe["allergens"] for a in user_allergens) if diet_ok and time_ok and allergen_ok: print(f"✓ {recipe['name']} is suitable") else: print(f"✗ {recipe['name']} doesn't meet requirements")
Conditional Expression — Python's Ternary
Python's one-line conditional. The syntax is value_if_true if condition else value_if_false — note the condition is in the middle, which is the opposite order to Java's condition ? a : b. Use it for simple assignments — not for complex logic.
# Java: String label = daysLeft <= 3 ? "URGENT" : "OK"; # Python: label = "URGENT" if days_left <= 3 else "OK" # Works great for building strings and setting defaults unit_label = "item" if qty == 1 else "items" print(f"{qty} {unit_label}") # "1 item" or "3 items" # Inline in a list comprehension inventory = [ {"name": "milk", "days_left": 2}, {"name": "eggs", "days_left": 10}, {"name": "yogurt", "days_left": 1}, ] alerts = [ f"⚠ {i['name']}" if i["days_left"] <= 3 else f"✓ {i['name']}" for i in inventory ] # → ["⚠ milk", "✓ eggs", "⚠ yogurt"]
Short-Circuit Evaluation — and / or as Default Values
Like JavaScript, Python's and/or use short-circuit evaluation and return one of their operands — not just True/False. This enables an idiomatic pattern for defaults. Note: prefer the walrus operator or explicit if for clarity in most cases.
# or returns the first truthy value, or the last value name = "" display_name = name or "Unknown ingredient" # → "Unknown ingredient" (name is falsy/empty) user_limit = None max_items = user_limit or 50 # → 50 (None is falsy) # and returns the first falsy value, or the last value # (less commonly used for defaults) days_left = 5 message = days_left and f"{days_left} days left" # → "5 days left" (days_left is truthy, so and returns the second) days_left = 0 message = days_left and f"{days_left} days left" # → 0 (days_left is falsy, and returns it immediately)
match Statement — Python's switch Python 3.10+
Python finally got a switch-like statement in version 3.10. It's far more powerful than Java's switch — it can match on values, types, structures, and even destructure objects. The _ case is the default (like Java's default:).
meal_type = "dinner" # Basic value matching (like Java switch) match meal_type: case "breakfast": suggestions = ["eggs", "toast", "yogurt"] case "lunch": suggestions = ["soup", "sandwich", "salad"] case "dinner": suggestions = ["pasta", "chicken", "curry"] case _: # default — like Java's default: suggestions = [] # Match multiple values in one case (use | for OR) match meal_type: case "breakfast" | "brunch": print("Morning meal") case "lunch" | "dinner": print("Main meal") case _: print("Snack") # Match with a guard condition (if clause inside case) days_left = 2 match days_left: case n if n <= 0: print("Expired") case n if n <= 3: print(f"Expiring soon — {n} day(s) left") case _: print("Plenty of time")

📋 Quick Reference — Operators

OperatorMeaningExampleJava/JS equivalent
==Equal (by value)qty == 0== (primitives) / .equals() (objects)
!=Not equalname != "milk"!=
< <= > >=Comparisondays <= 3same symbols
isIdentity (same object)val is None== for object references
is notNot identicalval is not None!= null
inMembership"milk" in pantry.contains() / .includes()
not inNot a member"nuts" not in allergens!list.contains()
andLogical ANDa and b&&
orLogical ORa or b||
notLogical NOTnot pantry!
a < b < cChained comparison0 < qty <= 100no equivalent — must use &&
x if cond else yConditional expression"yes" if ok else "no"cond ? x : y
match / caseStructural matchingmatch meal_type:switch (but more powerful)
any()True if any element truthyany(x > 0 for x in qtys)stream().anyMatch()
all()True if all elements truthyall(x > 0 for x in qtys)stream().allMatch()
⚠ Gotchas for Java / JavaScript Programmers:

== vs is — especially with Noneval == None works but is considered bad practice. Always write val is None. The reason: == can be overridden by a class's __eq__ method, so a custom object could make obj == None return True even when it isn't None. is None is always reliable.

0 and 0.0 are falsy — this catches Java programmers. If you have a quantity field that could legitimately be 0, writing if not quantity: will incorrectly fire when the quantity is zero. Be explicit: if quantity is None: to check for missing vs. if quantity == 0: to check for zero stock.

The conditional expression order — Python's ternary is value_if_true if condition else value_if_false. Java/JS is condition ? value_if_true : value_if_false. The condition is in the middle in Python, which feels backwards at first but reads naturally as a sentence: "give me 'urgent' if it's expiring else 'ok'."

match requires Python 3.10+ — if you're on an older Python, use elif chains instead. Check your Python version with python --version. Modern systems (2024+) generally ship with 3.10 or later.