Python's if and else Statements:

In Python, if and else statements are used for conditional execution. They allow your program to make decisions and execute different blocks of code based on whether certain conditions are true or false. This is a core concept in programming, enabling dynamic and responsive applications.



1. The if Statement :

The if statement is the simplest form of conditional control. It executes a block of code only if a specified condition evaluates to True.


Syntax:

if condition:
    # Code to execute if the condition is True
    # (Indented block)


Key Points :


Example :

#Example 1.1: Simple if statement
age = 20
if age >= 18:
    print("You are eligible to vote.")
print("This line runs regardless of the condition.")

Explanation :

In this example, age >= 18 evaluates to True, so "You are eligible to vote." is printed. The last print statement is outside the if block, so it always executes.



What if the condition is False?

# Example 1.2 : If condition is False
temperature = 25
if temperature > 30:
    print("It's a hot day!")
print("Enjoy the weather!")

Explanation :

Here, temperature > 30 is False. Therefore, the indented print statement inside the if block is skipped. "Enjoy the weather!" is still printed.



2. The if-else Statement :

The if-else statement provides an alternative path of execution when the if condition is False.


Syntax:

if condition:
    # Code to execute if the condition is True
else:
    # Code to execute if the condition is False


Key Points :


Example :

#Example 2.1: if-else statement
num = 7
if num % 2 == 0:
    print(f"{num} is an even number.")
else:
    print(f"{num} is an odd number.")
# Example 2.2: User input with if-else
user_input = input("Enter a number: ")
number = int(user_input) # Convert input to integer
if number > 0:
    print("The number is positive.")
else:
    print("The number is non-positive (zero or negative).")

Explanation :

In Example 2.1, 7 % 2 == 0 is False, so the else block executes. In Example 2.2, the program takes user input, converts it to an integer, and then checks if it's positive or not.



3. The if-elif-else Ladder :

When you have multiple conditions to check, the if-elif-else (pronounced "if-else if-else") ladder is used. elif is short for "else if".


Syntax:

if condition1:
    # Code to execute if condition1 is True
elif condition2:
    # Code to execute if condition1 is False AND condition2 is True
elif condition3:
    # Code to execute if condition1 and condition2 are False AND condition3 is True
else:
    # Code to execute if all preceding conditions (condition1, condition2, condition3, etc.) are False


Key Points :


Example :

# Example 3.1: Grade calculation
score = 85
if score >= 90:
    print("Grade: A")
elif score >= 80:
    print("Grade: B")
elif score >= 70:
    print("Grade: C")
elif score >= 60:
    print("Grade: D")
else:
    print("Grade: F")
# Example 3.2: Time-based greeting
import datetime
current_hour = datetime.datetime.now().hour
if current_hour < 12:
    print("Good morning!")
elif 12 <= current_hour < 18:
    print("Good afternoon!")
else:
    print("Good evening!")

Explanation :

In Example 3.1, score >= 90 is False, but score >= 80 is True, so "Grade: B" is printed, and the rest of the ladder is ignored. Example 3.2 dynamically greets the user based on the current hour.



4. Nested if-else Statements :

You can place if-else statements inside other if-else statements. This is called nesting. It's useful when you need to check multiple layers of conditions.


Syntax :

if outer_condition:
    # Code for outer_condition being True
    if inner_condition1:
        # Code for inner_condition1 being True
    else:
        # Code for inner_condition1 being False
else:
    # Code for outer_condition being False
    if another_inner_condition:
        # Code for another_inner_condition being True
    else:
        # Code for another_inner_condition being False


Key Points :


Example :

# Example 4.1: Movie ticket pricing with nested if-else
age = 15
is_student = True
if age < 18:
    if is_student:
        print("Student discount: Ticket price is $5.")
    else:
        print("Child price: Ticket price is $8.")
else:
    # Age is 18 or above
    if age >= 60:
        print("Senior discount: Ticket price is $7.")
    else:
        print("Adult price: Ticket price is $12.")

Explanation :

Here, the outer if checks the age. If age < 18 is true, then an inner if checks is_student. If age >= 18 is true (the else block of the outer if), then another inner if checks for senior discount.



5. Logical Operators (and, or, not) :

You can combine multiple conditions using logical operators to create more complex conditional expressions.


Example :

# Example 5.1: Using 'and'
temperature = 28
is_sunny = True
if temperature > 25 and is_sunny:
    print("Great day for an outdoor activity!")
else:
    print("Might be better to stay indoors or find another activity.")
# Example 5.2: Using 'or'
has_ticket = False
has_invitation = True
if has_ticket or has_invitation:
    print("Welcome to the event!")
else:
    print("Sorry, you need a ticket or an invitation to enter.")
# Example 5.3: Using 'not'
is_logged_in = False
if not is_logged_in:
    print("Please log in to access this feature.")
else:
    print("Welcome, user!")
# Example 5.4: Combining logical operators
age = 22
has_drivers_license = True
has_car = False
if (age >= 18 and has_drivers_license) and not has_car:
    print("You can drive, but you need a car!")
elif (age >= 18 and has_drivers_license) and has_car:
    print("You're all set to drive!")
else:
    print("You cannot drive yet or don't have a license.")


6. Ternary Operator (Conditional Expressions - Advanced Basic):

For simple if-else assignments, Python offers a concise one-line syntax called the ternary operator or conditional expression.


Syntax:

value_if_true if condition else value_if_false


Key Points :


Example :

# Example 6.1: Simple even/odd check
number = 10
status = "Even" if number % 2 == 0 else "Odd"
print(f"The number {number} is {status}.")
# Example 6.2: Assigning a message
is_open = True
message = "Store is open!" if is_open else "Store is closed."
print(message)
# Example 6.3: Using directly in print
score = 75
print("Passed" if score >= 60 else "Failed")


7. Chained Comparisons (Advanced) :

Python allows you to chain comparison operators, which can make your conditions more readable, especially when checking if a value falls within a range.


Syntax:

lower_bound <= value <= upper_bound

This is equivalent to lower_bound <= value and value <= upper_bound.


Example :

# Example 7.1: Checking if a number is within a range
num = 15
if 10 <= num <= 20:
    print(f"{num} is between 10 and 20 (inclusive).")
else:
    print(f"{num} is outside the range 10-20.")
# Example 7.2: Grade check with chained comparison
score = 88
if 90 <= score <= 100:
    print("Excellent (A)")
elif 80 <= score < 90: # Note: 'score < 90' is naturally handled by elif order, but explicit range is clearer
    print("Very Good (B)")
else:
    print("Needs Improvement")


8. if with in and not in Operators (Advanced) :

These operators are useful for checking membership in sequences (strings, lists, tuples, sets, dictionaries).


Syntax:

element in sequence
element not in sequence

Example :

# Example 8.1: Checking if an item is in a list
fruits = ["apple", "banana", "cherry"]
favorite_fruit = "banana"
if favorite_fruit in fruits:
    print(f"Yes, {favorite_fruit} is in the list.")
else:
    print(f"No, {favorite_fruit} is not in the list.")
# Example 8.2: Checking if a character is in a string
text = "Hello World"
if "o" in text:
    print("The letter 'o' is in the text.")
# Example 8.3: Checking if an item is NOT in a list
disallowed_words = ["badword1", "badword2"]
user_comment = "This is a good comment."
if user_comment not in disallowed_words:
    print("Comment approved.")
else:
    print("Comment contains disallowed words.")


9. Truthiness and Falsiness (Deep Dive) :

In Python, many values are inherently considered "truthy" or "falsy" when evaluated in a boolean context (like an if condition), even if they are not explicitly True or False.



Falsy Values :



Truthy Values :


Example :

element in sequence
element not in sequence

Example :

# Example 9.1: Truthiness of numbers
if 0:
    print("This will not print (0 is falsy)")
if 1:
    print("This will print (1 is truthy)")
if -5:
    print("This will print (-5 is truthy)")
# Example 9.2: Falsiness of empty sequences
my_list = []
if my_list:
    print("List is not empty.")
else:
    print("List is empty (falsy).")
my_string = "Hello"
if my_string:
    print("String is not empty.")
else:
    print("String is empty (falsy).")
# Example 9.3: Falsiness of None
value = None
if value:
    print("Value is not None.")
else:
    print("Value is None (falsy).")


10. if with try-except (Advanced Error Handling with Conditionals) :

Often, you'll need to check for conditions that might raise errors (exceptions). try-except blocks are used for this, and if statements can be used within them to handle different scenarios after an exception.


Example:

# Example 10.1: Handling invalid input
try:
    user_input = input("Enter a number: ")
    number = int(user_input)
    if number % 2 == 0:
        print(f"{number} is an even number.")
    else:
        print(f"{number} is an odd number.")
except ValueError:
    print("Invalid input! Please enter a valid integer.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

Explanation :

The try block attempts to convert user_input to an integer. If the input is not a valid integer (e.g., "hello"), a ValueError is raised, and the except ValueError block is executed. If the conversion is successful, the if-else statement proceeds normally.



11. if with Functions (High Level) :

Conditions are often used within functions to control their behavior and return different results based on inputs.


Example:

# Example 11.1: Function returning different values
def get_discounted_price(original_price, customer_type):
    if customer_type == "premium":
        return original_price * 0.8  # 20% discount
    elif customer_type == "student":
        return original_price * 0.9  # 10% discount
    else:
        return original_price # No discount
price1 = get_discounted_price(100, "premium")
print(f"Premium price: ${price1}")
price2 = get_discounted_price(100, "regular")
print(f"Regular price: ${price2}")
# Example 11.2: Function with validation
def divide_numbers(a, b):
    if b == 0:
        print("Error: Cannot divide by zero!")
        return None # Return None to indicate failure
    else:
        return a / b
result1 = divide_numbers(10, 2)
if result1 is not None:
    print(f"Result of division: {result1}")
result2 = divide_numbers(5, 0)
if result2 is None: # Check if the function returned None
    print("Division failed as expected.")


12. if with List Comprehensions and Generator Expressions (Advanced/Concise) :

if can be embedded within list comprehensions and generator expressions to filter elements or apply conditional transformations.


Syntax (Filtering) :

[expression for item in iterable if condition]


Syntax (Conditional Expression within Comprehension) :

[value_if_true if condition else value_if_false for item in iterable]

Example :

# Example 12.1: Filtering even numbers from a list
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = [num for num in numbers if num % 2 == 0]
print(f"Even numbers: {even_numbers}") # Output: [2, 4, 6, 8, 10]
# Example 12.2: Applying conditional transformation
transformed_numbers = [num * 2 if num % 2 == 0 else num for num in numbers]
print(f"Transformed numbers: {transformed_numbers}") # Output: [1, 4, 3, 8, 5, 12, 7, 16, 9, 20]
# Example 12.3: Generator expression (similar to list comprehension but lazy evaluation)
squared_odds = (num**2 for num in numbers if num % 2 != 0)
print("Squared odd numbers (generator):")
for sq in squared_odds:
    print(sq)


13. Short-Circuit Evaluation (Deep Dive) :

Python's logical operators (and, or) use short-circuit evaluation. This means that they evaluate conditions only as much as necessary to determine the overall result.

This can be useful for performance optimization and preventing errors.


Example:

# Example 13.1: Short-circuiting with 'and' to prevent ZeroDivisionError
def check_and_divide(numerator, denominator):
    # If denominator is 0, the first part is False, and (numerator / denominator) is never evaluated
    if denominator != 0 and (numerator / denominator) > 5:
        print("Division result is greater than 5.")
    else:
        print("Cannot divide by zero or result is not greater than 5.")

check_and_divide(10, 2)
check_and_divide(10, 0) # No ZeroDivisionError
check_and_divide(10, 3) # 3.33 is not > 5

# Example 13.2: Short-circuiting with 'or'
def is_valid_input(value):
    print(f"Checking value: {value}")
    return value is not None and value != ""

# If is_valid_input("hello") is True, is_valid_input("world") is NOT called.
if is_valid_input("hello") or is_valid_input("world"):
    print("At least one input is valid.")


14. match-case Statement (Python 3.10+) - Structured Pattern Matching :

While not strictly if-else, Python 3.10 introduced the match-case statement, which is a powerful way to handle multiple conditions in a more structured way, especially when dealing with different data patterns. It's an alternative to long if-elif-else chains for certain scenarios.


Syntax :

match subject:
    case pattern1:
        # Code if subject matches pattern1
    case pattern2:
        # Code if subject matches pattern2
    case _: # The "wildcard" or default case (like else)
        # Code if no other pattern matches

Example :

# Example 14.1: Basic match-case
command = "start"
match command:
    case "start":
        print("Starting the system...")
    case "stop":
        print("Stopping the system...")
    case "restart":
        print("Restarting the system...")
    case _: # Default case
        print("Unknown command.")

# Example 14.2: Match-case with multiple values or patterns
status_code = 403
match status_code:
    case 200:
        print("OK")
    case 400 | 401 | 403: # Multiple patterns for the same action
        print("Client error (Bad Request, Unauthorized, or Forbidden)")
    case 500:
        print("Server error")
    case _:
        print("Other status code")
# Example 14.3: Match-case with if-guard (conditional matching)
point = (10, -5) # A tuple representing (x, y) coordinates
match point:
    case (x, y) if x > 0 and y > 0:
        print(f"Point ({x},{y}) is in the first quadrant.")
    case (x, y) if x < 0 and y > 0:
        print(f"Point ({x},{y}) is in the second quadrant.")
    case (x, y) if x < 0 and y < 0:
        print(f"Point ({x},{y}) is in the third quadrant.")
    case (x, y) if x > 0 and y < 0:
        print(f"Point ({x},{y}) is in the fourth quadrant.")
    case (0, y) if y != 0:
        print(f"Point ({y}) is on the Y-axis.")
    case (x, 0) if x != 0:
        print(f"Point ({x}) is on the X-axis.")
    case (0, 0):
        print("Point is at the origin.")
    case _:
        print("Not a 2D point or unhandled case.")

Note on match-case: While it uses patterns and conditions (if guards), it's a distinct control flow statement from the if-elif-else ladder. It excels in pattern matching against various data structures, not just simple boolean conditions.



Best Practices and Common Pitfalls :

# Bad example (will never reach the second elif if score >= 70)
score = 85
if score >= 70:
    print("C")
elif score >= 80: # This will never be reached if score is 85, as the first condition already matched
    print("B")
# Good example
if score >= 80:
    print("B")
elif score >= 70:
    print("C")
# Instead of:
color = "red"
if color == "red":
    code = "#FF0000"
elif color == "blue":
    code = "#0000FF"
# ...
# Use a dictionary:
color_codes = {"red": "#FF0000", "blue": "#0000FF", "green": "#00FF00"}
color = "red"
code = color_codes.get(color, "Unknown") # .get() allows a default if key not found
print(code)