Python – Conditional Statements

Introduction

Every meaningful program needs to make decisions. Whether you are validating user input, routing requests, or handling edge cases, conditional statements are how your code responds to different situations at runtime. They are the foundation of control flow — the mechanism that determines which lines of code execute and in what order.

In Python, conditionals are clean, readable, and indentation-driven. There are no curly braces or explicit end keywords. If you are coming from Java, C++, or JavaScript, you will find Python’s approach refreshingly minimal. This tutorial walks through every conditional construct Python offers, from basic if statements to the modern match-case pattern matching introduced in Python 3.10.

Comparison Operators

Before writing conditionals, you need to understand the operators that produce True or False values. These are the building blocks of every condition you will ever write.

  • == — Equal to: checks if two values are the same
  • != — Not equal to: checks if two values differ
  • < — Less than
  • > — Greater than
  • <= — Less than or equal to
  • >= — Greater than or equal to
x = 10
y = 20

print(x == y)   # False
print(x != y)   # True
print(x < y)    # True
print(x > y)    # False
print(x <= 10)  # True
print(x >= 15)  # False

One critical distinction: == checks equality, while is checks identity (whether two variables point to the same object in memory). For value comparison, always use ==.

The if Statement

The if statement is the most fundamental decision-making construct. It evaluates an expression, and if that expression is True, the indented block beneath it executes. If the expression is False, Python skips the block entirely.

# Basic if statement
temperature = 35

if temperature > 30:
    print("It's a hot day.")
    print("Stay hydrated!")

Key point: Python uses indentation (typically 4 spaces) to define the body of an if block. The first line that returns to the previous indentation level marks the end of the block. There are no braces, no end if — just consistent indentation.

# Age verification example
user_age = 21

if user_age >= 18:
    print("Access granted. You are old enough to enter.")

print("This line runs regardless of the condition.")

The if-else Statement

When you need to handle both outcomes of a condition, use if-else. The else block runs when the if condition evaluates to False.

# Age verification with else
age = 16

if age >= 18:
    print("You are eligible to vote.")
else:
    print(f"You must wait {18 - age} more year(s) to vote.")
# Even or odd check
number = 7

if number % 2 == 0:
    print(f"{number} is even.")
else:
    print(f"{number} is odd.")

The if-elif-else Chain

When you have more than two possible outcomes, chain conditions together with elif (short for “else if”). Python evaluates each condition from top to bottom and executes the first block whose condition is True. If none match, the else block runs as a fallback.

# Grade calculator
score = 82

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
elif score >= 60:
    grade = "D"
else:
    grade = "F"

print(f"Score: {score}, Grade: {grade}")
# Output: Score: 82, Grade: B

Notice the order matters. Since Python stops at the first match, we check from highest to lowest. If we reversed the order, a score of 95 would match score >= 60 first and incorrectly receive a “D”.

# Simple calculator using if-elif
num1 = 15
num2 = 4
operator = "/"

if operator == "+":
    result = num1 + num2
elif operator == "-":
    result = num1 - num2
elif operator == "*":
    result = num1 * num2
elif operator == "/":
    if num2 != 0:
        result = num1 / num2
    else:
        result = "Error: Division by zero"
else:
    result = "Error: Unknown operator"

print(f"{num1} {operator} {num2} = {result}")
# Output: 15 / 4 = 3.75
# User role-based access control
user_role = "editor"

if user_role == "admin":
    print("Full access: read, write, delete, manage users")
elif user_role == "editor":
    print("Editor access: read and write")
elif user_role == "viewer":
    print("Viewer access: read only")
else:
    print("Unknown role. Access denied.")

Nested Conditionals

You can place if statements inside other if statements. This is useful when a secondary condition only makes sense after a primary condition is met.

# Nested conditional: age and membership check
age = 25
has_membership = True

if age >= 18:
    if has_membership:
        print("Welcome! You have full access.")
    else:
        print("You are old enough, but you need a membership.")
else:
    print("Sorry, you must be 18 or older.")
# Login validation with nested checks
username = "folauk"
password = "secure123"
is_active = True

if username == "folauk":
    if password == "secure123":
        if is_active:
            print("Login successful.")
        else:
            print("Account is deactivated.")
    else:
        print("Incorrect password.")
else:
    print("User not found.")

A word of caution: While nesting works, deeply nested conditionals (3+ levels) become difficult to read and maintain. If you find yourself going deeper than two levels, consider refactoring with early returns, guard clauses, or by extracting logic into helper functions. Here is the same login example refactored:

# Refactored: use early returns to avoid deep nesting
def authenticate(username, password, is_active):
    if username != "folauk":
        return "User not found."
    if password != "secure123":
        return "Incorrect password."
    if not is_active:
        return "Account is deactivated."
    return "Login successful."

result = authenticate("folauk", "secure123", True)
print(result)

Logical Operators: and, or, not

Logical operators let you combine multiple conditions into a single expression. Mastering them is essential for writing expressive, readable conditionals.

and — Both conditions must be True

# Both conditions must be True
age = 25
has_license = True

if age >= 18 and has_license:
    print("You are allowed to drive.")
else:
    print("You cannot drive.")
# Checking a value is within a range
score = 85

if score >= 80 and score <= 89:
    print("You got a B.")

or — At least one condition must be True

# At least one condition must be True
is_weekend = True
is_holiday = False

if is_weekend or is_holiday:
    print("You can sleep in today!")
else:
    print("Time to get up for work.")
# User role check with or
role = "moderator"

if role == "admin" or role == "moderator":
    print("You can delete posts.")

not — Inverts a boolean

# Invert a condition
is_logged_in = False

if not is_logged_in:
    print("Please log in to continue.")

Combining Logical Operators

# Complex condition with and, or, not
age = 30
is_student = False
has_coupon = True

if (age < 18 or is_student) and not has_coupon:
    print("Standard discount applied.")
elif has_coupon:
    print("Coupon discount applied.")
else:
    print("No discount available.")

Operator precedence: not is evaluated first, then and, then or. When in doubt, use parentheses to make your intent explicit. Your future self (and your teammates) will thank you.

Truthiness and Falsiness in Python

Python does not require conditions to be strictly True or False. Every object in Python has an inherent boolean value. Understanding what is “truthy” and “falsy” will make your conditionals more Pythonic.

Falsy values (evaluate to False):

  • False
  • None
  • 0 (integer zero), 0.0 (float zero), 0j (complex zero)
  • "" (empty string)
  • [] (empty list), () (empty tuple), {} (empty dict), set() (empty set)

Everything else is truthy, including non-zero numbers, non-empty strings, and non-empty collections.

# Truthy/Falsy in action
name = ""

if name:
    print(f"Hello, {name}!")
else:
    print("Name is empty. Please provide a name.")
# Checking if a list has items
shopping_list = ["milk", "eggs"]

if shopping_list:
    print(f"You have {len(shopping_list)} item(s) to buy.")
else:
    print("Your shopping list is empty.")
# Using truthiness for None checks
config = None

if not config:
    print("No configuration loaded. Using defaults.")

This is idiomatic Python. Instead of writing if len(my_list) > 0:, experienced Python developers write if my_list:. It is cleaner, faster, and communicates intent more directly.

The Ternary Operator (Conditional Expression)

Python supports a one-line if-else expression, often called the ternary operator. The syntax is:

# Syntax: value_if_true if condition else value_if_false

age = 20
status = "adult" if age >= 18 else "minor"
print(status)  # Output: adult
# Ternary for assigning default values
user_input = ""
username = user_input if user_input else "Anonymous"
print(f"Welcome, {username}!")  # Output: Welcome, Anonymous!
# Ternary in a function return
def get_access_level(role):
    return "full" if role == "admin" else "limited"

print(get_access_level("admin"))   # Output: full
print(get_access_level("viewer"))  # Output: limited

Use ternary expressions for simple, short conditions. If the logic is complex or involves multiple branches, stick with a regular if-elif-else block for readability.

The match-case Statement (Python 3.10+)

Python 3.10 introduced structural pattern matching with the match-case statement. If you are familiar with switch statements from other languages, this is Python’s more powerful equivalent. It does not just match values — it can destructure data, match types, and bind variables.

# Basic match-case: HTTP status code handler
status_code = 404

match status_code:
    case 200:
        print("OK - Request succeeded.")
    case 301:
        print("Moved Permanently.")
    case 404:
        print("Not Found - Resource does not exist.")
    case 500:
        print("Internal Server Error.")
    case _:
        print(f"Unhandled status code: {status_code}")

The underscore _ is the wildcard pattern — it matches anything and acts as the default case.

# match-case with combined patterns using |
command = "quit"

match command:
    case "start" | "run":
        print("Starting the application...")
    case "stop" | "quit" | "exit":
        print("Shutting down...")
    case "status":
        print("Application is running.")
    case _:
        print(f"Unknown command: {command}")
# match-case with pattern destructuring
point = (3, 0)

match point:
    case (0, 0):
        print("Origin")
    case (x, 0):
        print(f"On the X-axis at x={x}")
    case (0, y):
        print(f"On the Y-axis at y={y}")
    case (x, y):
        print(f"Point at ({x}, {y})")
# Output: On the X-axis at x=3

match-case is especially useful for command parsing, event handling, and working with structured data like API responses or ASTs. However, note that it requires Python 3.10 or later, so check your target Python version before using it in production code.

The pass Statement

In Python, if statements cannot have an empty body. If you need a placeholder — perhaps you plan to implement the logic later — use the pass statement to avoid a syntax error.

# Placeholder for future implementation
if 3 > 2:
    pass  # TODO: implement this logic later

In practice, you will use pass during development as a stub. It does nothing but tells Python “I intentionally left this empty.”

Common Pitfalls

These are mistakes that every Python developer makes at some point. Knowing them ahead of time will save you hours of debugging.

1. Using = instead of ==

# WRONG: = is assignment, not comparison
# if x = 10:    # SyntaxError!

# CORRECT: == is comparison
x = 10
if x == 10:
    print("x is 10")

Unlike C or Java, Python will raise a SyntaxError if you use = in a condition. This is actually a helpful safeguard, but it still catches beginners off guard.

2. Indentation Errors

# WRONG: inconsistent indentation
# if True:
#     print("indented with 4 spaces")
#       print("indented with 6 spaces")  # IndentationError!

# CORRECT: consistent 4-space indentation
if True:
    print("line 1")
    print("line 2")

Python enforces indentation as part of its syntax. Mix tabs and spaces, or use inconsistent spacing, and you will get an IndentationError. Configure your editor to insert 4 spaces when you press Tab. This is the Python community standard (PEP 8).

3. Comparing Different Types

# Potential surprise: string vs integer comparison
user_input = "5"
threshold = 5

# This is False because "5" (str) != 5 (int)
if user_input == threshold:
    print("Match")
else:
    print("No match")  # This prints

# Fix: convert types explicitly
if int(user_input) == threshold:
    print("Match")  # Now this prints

Python does not implicitly convert types during comparison. A string "5" is not equal to an integer 5. Always be explicit about type conversions, especially when working with user input.

Best Practices

1. Keep Conditions Simple and Readable

# Hard to read
if user.age >= 18 and user.is_active and not user.is_banned and user.email_verified:
    grant_access()

# Better: extract to a well-named variable or function
def is_eligible(user):
    return (
        user.age >= 18
        and user.is_active
        and not user.is_banned
        and user.email_verified
    )

if is_eligible(user):
    grant_access()

2. Use Early Returns to Reduce Nesting

# Deeply nested (avoid this)
def process_order(order):
    if order is not None:
        if order.is_valid:
            if order.in_stock:
                ship(order)

# Flat and clear (prefer this)
def process_order(order):
    if order is None:
        return
    if not order.is_valid:
        return
    if not order.in_stock:
        return
    ship(order)

3. Prefer Positive Conditions

# Harder to reason about
if not is_invalid:
    process()

# Clearer
if is_valid:
    process()

When naming boolean variables and writing conditions, aim for positive phrasing. is_active is easier to reason about than not is_inactive.

Practical Example: Putting It All Together

# Complete example: Student grade report generator
def calculate_grade(score):
    """Return a letter grade based on the numeric score."""
    if not isinstance(score, (int, float)):
        return "Invalid"
    if score < 0 or score > 100:
        return "Invalid"
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    elif score >= 70:
        return "C"
    elif score >= 60:
        return "D"
    return "F"

def get_status(grade):
    """Return pass/fail status."""
    return "Pass" if grade not in ("F", "Invalid") else "Fail"

# Student records
students = [
    {"name": "Alice", "score": 92},
    {"name": "Bob", "score": 75},
    {"name": "Charlie", "score": 58},
    {"name": "Diana", "score": 88},
]

for student in students:
    grade = calculate_grade(student["score"])
    status = get_status(grade)
    print(f"{student['name']}: {student['score']}% -> {grade} ({status})")

Output:

Alice: 92% -> A (Pass)
Bob: 75% -> C (Pass)
Charlie: 58% -> F (Fail)
Diana: 88% -> B (Pass)

Key Takeaways

  • Indentation is syntax in Python. Every if, elif, and else block must be consistently indented (use 4 spaces).
  • if-elif-else is the workhorse of Python conditionals. Order your conditions from most specific to least specific.
  • Comparison operators (==, !=, <, >, <=, >=) produce boolean values that drive your conditions.
  • Logical operators (and, or, not) let you combine and invert conditions. Remember precedence: not > and > or.
  • Truthiness/Falsiness: empty collections, 0, None, and "" are all falsy. Use this to write concise, Pythonic checks.
  • Ternary expressions (x if condition else y) are great for simple inline conditionals, but do not overuse them for complex logic.
  • match-case (Python 3.10+) is powerful for pattern matching, especially when working with structured data or command dispatching.
  • Avoid deep nesting. Use guard clauses and early returns to keep your code flat and readable.
  • Be explicit about types. Python does not coerce types in comparisons. Always convert user input to the expected type before comparing.

 

Source on Github




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *