if, elif & else

Conditional statements let a program make decisions. Python's if runs a block only when a condition is true, elif ("else if") checks further conditions in turn, and else catches everything left over.

if

PY if.py
balance = 120
price = 80

if balance >= price:
    print("Purchase approved")
    balance -= price

print("Balance:", balance)
Output
Purchase approved
Balance: 40

The condition is followed by a colon, and the block is indented. When the condition is false, the indented block is skipped.

else

PY else.py
hour = 20

if hour < 18:
    print("Good afternoon")
else:
    print("Good evening")
Output
Good evening

elif

Conditions are checked from top to bottom, and only the first true branch runs:

PY elif.py
def grade(score):
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    elif score >= 70:
        return "C"
    elif score >= 60:
        return "D"
    else:
        return "F"

for s in [95, 83, 71, 64, 30]:
    print(s, grade(s))
Output
95 A
83 B
71 C
64 D
30 F

Because the checks happen in order, the second condition doesn't need to say score < 90 — that's already guaranteed if we got that far.

Combining conditions

PY combine.py
age = 25
has_ticket = True
is_vip = False

if age >= 18 and has_ticket:
    print("Welcome in")

if is_vip or age >= 65:
    print("Free drink")
else:
    print("Drinks are $5")

if not is_vip:
    print("Join our VIP club!")

temperature = 22
if 18 <= temperature <= 25:
    print("Perfect weather")
Output
Welcome in
Drinks are $5
Join our VIP club!
Perfect weather

Chained comparisons like 18 <= temperature <= 25 are a Python nicety that reads just like maths.

Checking membership

PY membership.py
command = "quit"

if command in ("exit", "quit", "q"):
    print("Goodbye!")

allowed = {"admin", "editor"}
role = "viewer"
if role not in allowed:
    print(f"{role!r} cannot edit")
Output
Goodbye!
'viewer' cannot edit

Testing against a tuple or set with in is cleaner than chaining command == "exit" or command == "quit" or ….

Truthiness in conditions

PY truthy.py
items = []
name = "Ana"

if items:
    print(f"{len(items)} items")
else:
    print("No items")

if name:
    print(f"Hello, {name}")
Output
No items
Hello, Ana

Nested ifs vs guard clauses

Deeply nested conditions are hard to read. Inside functions, returning early for the special cases keeps the main path flat:

PY guards.py
def checkout(user, cart):
    if user is None:
        return "Please log in"
    if not cart:
        return "Your cart is empty"
    if not user.get("verified"):
        return "Please verify your email"
    return f"Charging {user['name']} for {len(cart)} items"

print(checkout(None, ["book"]))
print(checkout({"name": "Ana", "verified": True}, ["book", "pen"]))
Output
Please log in
Charging Ana for 2 items

Conditional expressions

For choosing between two values, the one-line conditional expression is often clearer:

PY ternary.py
stock = 3
label = "in stock" if stock > 0 else "sold out"
print(label)

count = 1
print(f"{count} {'item' if count == 1 else 'items'}")
Output
in stock
1 item

pass: an empty block

A block can't be empty in Python. Use pass as a placeholder while you're still writing code:

PY pass.py
debug = False

if debug:
    pass  # TODO: add logging
else:
    print("running normally")
Output
running normally

Try it yourself

Try it yourself
Console output