Python - If/Elif/Else Statement

Every useful program makes decisions. Should we grant access to this user? Is this input valid? Does this order qualify for free shipping? Conditional statements are how you encode these decisions in...

Key Insights

  • Conditional statements are the decision-making backbone of every Python program—master them first, and everything else becomes easier to understand.
  • The order of your elif conditions matters significantly; Python evaluates them top-to-bottom and stops at the first match.
  • Deep nesting is a code smell; use guard clauses and combined conditions to write flatter, more readable code.

Introduction to Conditional Logic

Every useful program makes decisions. Should we grant access to this user? Is this input valid? Does this order qualify for free shipping? Conditional statements are how you encode these decisions in code.

At its core, a conditional statement evaluates an expression to either True or False, then executes different code paths based on the result. This is fundamental flow control—the ability to branch your program’s execution based on runtime conditions.

Think of it like checking if a door is locked before deciding your next action:

door_locked = True

if door_locked:
    print("Use your key to unlock the door")
    print("Then enter the house")
else:
    print("Walk right in")

This simple pattern—check a condition, do one thing or another—scales up to handle complex business logic, validation rules, and state management. Let’s break down each component.

The if Statement

The if statement is the foundation. It evaluates a boolean expression and executes its code block only when that expression is True.

if condition:
    # This code runs only when condition is True
    do_something()

Notice the colon after the condition and the indentation of the code block. Python uses indentation (typically 4 spaces) to define code blocks rather than braces. This isn’t optional—it’s part of the syntax.

Here’s a practical example checking if a number is positive:

temperature = 25

if temperature > 0:
    print(f"Temperature is {temperature}°C (above freezing)")
    print("No risk of ice on the roads")

Python evaluates temperature > 0, which returns True since 25 is greater than 0. Both print statements execute.

Understanding Truthiness

Python doesn’t require explicit boolean values. It evaluates the “truthiness” of any expression:

user_input = "hello"

if user_input:  # Non-empty strings are truthy
    print("User provided input")

items = []

if items:  # Empty lists are falsy
    print("This won't print")

Falsy values include: False, None, 0, 0.0, "" (empty string), [] (empty list), {} (empty dict), and set(). Everything else is truthy.

This is useful but can be a source of bugs. Be explicit when clarity matters:

# Ambiguous: does this check for None or zero?
if value:
    process(value)

# Explicit: clearly checking for None
if value is not None:
    process(value)

Adding Alternatives with else

The else clause provides a fallback when the if condition is False:

password = "secret123"
user_input = "wrongpassword"

if user_input == password:
    print("Login successful")
    print("Redirecting to dashboard...")
else:
    print("Invalid password")
    print("Please try again")

The else block has no condition—it catches everything that didn’t match the if. You can only have one else, and it must come last.

A common pattern is validation before processing:

def process_order(quantity):
    if quantity > 0:
        total = quantity * 29.99
        print(f"Order placed: {quantity} items, total ${total:.2f}")
    else:
        print("Error: Quantity must be positive")

Multiple Conditions with elif

When you have more than two possible outcomes, elif (short for “else if”) lets you chain conditions:

def get_letter_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"

print(get_letter_grade(85))  # Output: B
print(get_letter_grade(72))  # Output: C
print(get_letter_grade(45))  # Output: F

Python evaluates conditions from top to bottom and executes only the first matching block. This is critical—order matters.

Consider what happens if we reverse the order:

# WRONG: This always returns "F" for passing scores
def broken_grade(score):
    if score >= 60:
        return "D"  # 85 is >= 60, so this matches first!
    elif score >= 70:
        return "C"  # Never reached for scores >= 60
    elif score >= 80:
        return "B"  # Never reached
    elif score >= 90:
        return "A"  # Never reached
    else:
        return "F"

Always order your conditions from most specific to least specific, or from highest threshold to lowest when dealing with ranges.

Combining Conditions

Real-world logic often requires checking multiple conditions simultaneously. Python provides and, or, and not operators for this.

Using and

Both conditions must be True:

age = 25
has_membership = True

if age >= 18 and has_membership:
    print("Access granted to premium content")
else:
    print("Access denied")

Using or

At least one condition must be True:

is_admin = False
is_moderator = True

if is_admin or is_moderator:
    print("You can edit this post")

Using not

Inverts the boolean value:

maintenance_mode = False

if not maintenance_mode:
    print("System is operational")

Complex Conditions

You can combine these operators. Use parentheses for clarity:

def can_access_feature(user):
    age = user.get("age", 0)
    is_premium = user.get("is_premium", False)
    is_admin = user.get("is_admin", False)
    
    # Admins always have access, or premium users 18+
    if is_admin or (is_premium and age >= 18):
        return True
    else:
        return False

Nested vs. Combined Conditions

You could write nested conditionals instead:

# Nested approach - harder to read
if is_admin:
    return True
else:
    if is_premium:
        if age >= 18:
            return True
    return False

The combined approach is almost always cleaner. Nested conditionals should be a last resort when the logic truly requires different handling at each level.

Common Patterns and Best Practices

Avoid Deep Nesting

Deeply nested conditionals are hard to read and maintain:

# Hard to follow
def process_payment(user, amount):
    if user is not None:
        if user.is_active:
            if amount > 0:
                if user.balance >= amount:
                    user.balance -= amount
                    return "Payment successful"
                else:
                    return "Insufficient funds"
            else:
                return "Invalid amount"
        else:
            return "Account inactive"
    else:
        return "User not found"

Use Guard Clauses

Guard clauses check for invalid conditions early and return immediately:

# Much cleaner
def process_payment(user, amount):
    if user is None:
        return "User not found"
    
    if not user.is_active:
        return "Account inactive"
    
    if amount <= 0:
        return "Invalid amount"
    
    if user.balance < amount:
        return "Insufficient funds"
    
    user.balance -= amount
    return "Payment successful"

The logic flows linearly. Each guard clause handles one error case, and the happy path is at the end, unindented.

Ternary Expressions for Simple Cases

For simple if/else assignments, Python offers a one-line ternary expression:

# Instead of this:
if score >= 60:
    status = "Pass"
else:
    status = "Fail"

# Write this:
status = "Pass" if score >= 60 else "Fail"

Use this sparingly. If your ternary expression is hard to read at a glance, use the full if/else.

Avoid Redundant Conditions

Don’t compare booleans to True or False:

# Redundant
if is_valid == True:
    process()

# Clean
if is_valid:
    process()

# Redundant
if has_error == False:
    continue_processing()

# Clean
if not has_error:
    continue_processing()

Conclusion

The if/elif/else statement is deceptively simple but forms the backbone of program logic. Master these principles:

  • Use if for single conditions
  • Add else when you need a fallback
  • Chain elif for multiple exclusive conditions, ordered from most to least specific
  • Combine conditions with and, or, and not instead of nesting
  • Use guard clauses to keep your code flat and readable

Once you’re comfortable with these patterns, explore Python’s match statement (introduced in Python 3.10) for more complex pattern matching, and learn how conditionals interact with loops for iteration control. But get the fundamentals right first—clean conditional logic is the foundation of maintainable code.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.