Skip to content
elephantoo

Conditionals: if, elif, else & match

Lesson 6 of 38 14 min read

Branching, truthiness, combining conditions, guard clauses, the ternary expression and pattern matching.


Programs become useful when they can make decisions: show an error when a password is too short, give a discount to members, route a command to the right handler. In Python, decisions are written with if, elif and else — and, since Python 3.10, the powerful match statement.

if, elif, else#

Python
score = 85

if score >= 90:
    grade = "A"
elif score >= 75:
    grade = "B"
elif score >= 60:
    grade = "C"
else:
    grade = "D"

print(grade)
Output
B

How it works:

  • Python checks each condition top to bottom and runs the first block whose condition is true — then skips the rest.
  • elif ("else if") can appear any number of times; else is optional and must come last.
  • Each condition ends with a colon, and the block below it is indented.

Order matters. If the >= 60 check came first, a score of 95 would get a "C", because that condition would match before the others were even checked.

Truthy and falsy values#

A condition doesn't have to be a literal True/False. Python evaluates any value for truthiness:

FalsyTruthy
False, NoneTrue
0, 0.0any other number
"" (empty string)"0", " ", any non-empty string
[], (), {}, set()any non-empty collection

This lets you write natural checks:

Python
name = ""
cart = ["book"]

if not name:
    print("Please enter a name")
if cart:
    print(f"You have {len(cart)} item(s) in your cart")
Output
Please enter a name
You have 1 item(s) in your cart

Combining conditions#

Use and, or and not, and chain comparisons like in maths:

Python
age = 30
has_ticket = True
is_vip = False

if age >= 18 and has_ticket:
    print("Welcome in")
if is_vip or age > 65:
    print("Free drink")
if 18 <= age < 60:
    print("Standard fare")
Output
Welcome in
Standard fare

and binds tighter than or, so a or b and c means a or (b and c). Add parentheses whenever you mix them.

== vs is, and membership with in

== asks "are these equal?". is asks "are these the same object?". Use is only for singletons like None:

Python
value = None
if value is None:
    print("missing")

role = "editor"
if role in ("admin", "editor"):   # cleaner than role == "admin" or role == "editor"
    print("can publish")
Output
missing
can publish

Nested conditions and guard clauses#

You can put an if inside another if, but deep nesting quickly becomes hard to read:

Python
def can_checkout(user, cart):
    if user is not None:
        if user["verified"]:
            if cart:
                return True
    return False

A cleaner style is guard clauses: handle the failure cases first and return early, leaving the happy path unindented.

Python
def can_checkout(user, cart):
    if user is None:
        return False
    if not user["verified"]:
        return False
    if not cart:
        return False
    return True


print(can_checkout({"verified": True}, ["pen"]))
print(can_checkout({"verified": False}, ["pen"]))
Output
True
False

The conditional expression (ternary)#

For choosing between two values, Python has a one-line form: A if condition else B.

Python
stock = 0
label = "In stock" if stock > 0 else "Sold out"
print(label)

n = 7
print(f"{n} is {'even' if n % 2 == 0 else 'odd'}")
Output
Sold out
7 is odd

Use it for simple value choices only; don't nest them.

Structural pattern matching: match#

match compares a value against a series of patterns. For simple values it reads like a switch statement:

Python
def http_status(code):
    match code:
        case 200:
            return "OK"
        case 301 | 302:            # | means "or"
            return "Redirect"
        case 404:
            return "Not Found"
        case 500:
            return "Server Error"
        case _:                     # wildcard: anything else
            return "Unknown"


for code in (200, 302, 404, 418):
    print(code, http_status(code))
Output
200 OK
302 Redirect
404 Not Found
418 Unknown

Unlike a C/Java switch, there's no fall-through and no break needed — only the first matching case runs.

match really shines when you destructure data. Patterns can match the shape of sequences and dictionaries and capture parts into variables:

Python
def handle(command):
    match command.split():
        case ["quit"]:
            return "Bye!"
        case ["go", direction]:
            return f"Walking {direction}"
        case ["get", item, *rest]:
            return f"Picked up {item}" + (f" and {len(rest)} more" if rest else "")
        case _:
            return "Unknown command"


for c in ["go north", "get lamp", "get key coin gem", "quit", "dance"]:
    print(handle(c))
Output
Walking north
Picked up lamp
Picked up key and 2 more
Bye!
Unknown command

Dictionary patterns and guards (an extra if on a case) make it great for handling JSON-like data:

Python
def describe(event):
    match event:
        case {"type": "click", "x": x, "y": y} if x < 0 or y < 0:
            return "click outside the window"
        case {"type": "click", "x": x, "y": y}:
            return f"click at ({x}, {y})"
        case {"type": "key", "key": key}:
            return f"key {key!r} pressed"
        case _:
            return "unknown event"


print(describe({"type": "click", "x": 10, "y": 20}))
print(describe({"type": "click", "x": -5, "y": 20}))
print(describe({"type": "key", "key": "q", "shift": False}))
Output
click at (10, 20)
click outside the window
key 'q' pressed

Note that dictionary patterns match as long as the listed keys are present — extra keys like "shift" are ignored.

Use if/elif for ranges and general boolean logic; use match when you're checking one value against several shapes or constants.

Worked example: a BMI classifier#

Python
weight_kg = 68
height_m = 1.75

bmi = weight_kg / height_m ** 2

if bmi < 18.5:
    category = "underweight"
elif bmi < 25:
    category = "healthy"
elif bmi < 30:
    category = "overweight"
else:
    category = "obese"

print(f"BMI {bmi:.1f}: {category}")
Output
BMI 22.2: healthy

Because the conditions are checked in order, each elif only needs the upper bound — the lower bound is implied by the earlier checks failing.

Common mistakes#

  • Using = instead of == in a condition — Python raises a SyntaxError.
  • Forgetting the colon after if, elif, else or case.
  • Writing if x == "a" or "b": — this is always true, because "b" on its own is truthy. Write if x in ("a", "b"):.
  • Comparing to True: if is_ready == True: works but is unidiomatic; write if is_ready:.
  • Treating a bare name in a case as a constant. case limit: doesn't compare with a variable called limit — it captures anything into a new name limit. Use literals, dotted names (Color.RED) or a guard instead.

What's next#

Your programs can now choose. Next they'll learn to repeat: for and while loops, range, enumerate, zip and friends.

Check your understanding

Quick quiz

0/3 answered
  1. 1.Which branch runs when no if/elif condition is true?

  2. 2.Which of these values is truthy?

  3. 3.In a match statement, what does case _: do?

Finished reading?

Mark this lesson complete to track your progress.