8. Making Decisions with if Statements
In the programs we've written so far, Python executes every line of code from top to bottom, one statement after another. But real-world programs need to make decisions—to execute different code depending on different conditions. Should we display an error message? Should we calculate a discount? Should we ask for input again? The answer depends on the situation.
Conditional statements let your programs make these decisions. They allow Python to execute certain blocks of code only when specific conditions are true, and skip them otherwise. This chapter introduces Python's if statement and its variations, which form the foundation of decision-making in your programs.
By mastering conditional statements, you'll be able to write programs that respond intelligently to user input, handle different scenarios appropriately, and solve problems that require logical reasoning.
8.1) Simple if Statements
The most basic form of decision-making in Python is the simple if statement. It tells Python: "If this condition is true, execute this block of code. Otherwise, skip it and continue."
8.1.1) The Structure of an if Statement
Here's the basic syntax of an if statement:
if condition:
# Code to execute if condition is True
statement1
statement2
# ... more statementsLet's break down each part:
- The
ifkeyword: This starts the conditional statement - The condition: A boolean expression that evaluates to
TrueorFalse(from Chapter 7) - The colon (
:): This is required and marks the end of the condition line - The indented code block: All statements indented under the
ifare executed only when the condition isTrue
Indentation is critical in Python. The indented lines form a code block that belongs to the if statement. Python uses indentation (typically 4 spaces) to determine which statements are part of the conditional block.
Here's a simple example:
# temperature_check.py
temperature = 30
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # This always executesOutput:
It's a warm day!
Consider wearing light clothing.
Have a great day!In this example:
- The condition
temperature > 25evaluates toTrue(since 30 > 25) - Both indented
print()statements execute because they're part of theifblock - The final
print()statement always executes because it's not indented—it's not part of theifblock
Now let's see what happens when the condition is False:
# temperature_check_cool.py
temperature = 18
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # This always executesOutput:
Have a great day!This time:
- The condition
temperature > 25evaluates toFalse(since 18 is not greater than 25) - Both indented statements are skipped entirely
- Only the final
print()executes because it's outside theifblock
8.1.2) Using Conditions from Chapter 7
Any boolean expression from Chapter 7 can be used as a condition in an if statement. This includes:
Comparison operators:
# voting_eligibility.py
age = 16
if age >= 18:
print("You are eligible to vote.")
# Nothing prints because 16 >= 18 is False
score = 85
if score >= 60:
print("You passed the exam!") # Output: You passed the exam!Membership tests with in and not in:
# user_access.py
username = "alice"
banned_users = ["bob", "charlie", "dave"]
if username not in banned_users:
print(f"Welcome, {username}!") # Output: Welcome, alice!
favorite_color = "blue"
if "u" in favorite_color:
print("Your favorite color contains the letter 'u'.") # Output: Your favorite color contains the letter 'u'.Direct boolean values:
# weather_check.py
is_raining = True
if is_raining:
print("Don't forget your umbrella!") # Output: Don't forget your umbrella!Truthiness and falsiness (from Chapter 7.4):
# name_input.py
user_input = input("Enter your name: ")
if user_input: # Empty string is falsy, non-empty is truthy
print(f"Hello, {user_input}!")
else:
print("You didn't enter a name.")8.1.3) Multiple Statements in the if Block
You can include as many statements as you need in an if block. All indented statements under the if line belong to that block:
# bank_withdrawal.py
balance = 1500
withdrawal = 200
if withdrawal <= balance:
balance = balance - withdrawal # Subtract withdrawal from balance
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # Always executesOutput:
Withdrawal successful!
Your new balance is: $1300
Thank you for your transaction.
Transaction complete.All four statements execute because withdrawal <= balance is True. If we change the withdrawal to 2000:
# bank_withdrawal_insufficient.py
balance = 1500
withdrawal = 2000
if withdrawal <= balance:
balance = balance - withdrawal
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # Always executesOutput:
Transaction complete.Now none of the indented statements execute because the condition is False. The balance remains unchanged at 1500.
8.2) Using if-else for Either-Or Choices
Often you need to choose between two alternatives: execute one block of code if a condition is true, and a different block if it's false. The if-else statement handles this either-or decision-making.
8.2.1) The Structure of if-else
Here's the syntax:
if condition:
# Code to execute if condition is True
statement1
statement2
else:
# Code to execute if condition is False
statement3
statement4The else clause provides an alternative path. Exactly one of the two blocks will execute—never both, never neither.
Let's see a practical example:
# age_verification.py
age = int(input("Enter your age: "))
if age >= 18:
print("You are an adult.")
print("You can vote in elections.")
else:
print("You are a minor.")
print("You cannot vote yet.")
print("Thank you for providing your age.")If you enter 25:
You are an adult.
You can vote in elections.
Thank you for providing your age.If you enter 15:
You are a minor.
You cannot vote yet.
Thank you for providing your age.Notice that exactly one of the two blocks executes, depending on the condition. The final print() statement always executes because it's outside both blocks.
8.2.2) Making Binary Decisions
if-else is perfect for binary decisions where there are exactly two possible outcomes:
# even_odd_checker.py
number = int(input("Enter a number: "))
if number % 2 == 0:
print(f"{number} is even.")
else:
print(f"{number} is odd.")# password_verification.py
stored_password = "python123"
entered_password = input("Enter password: ")
if entered_password == stored_password:
print("Access granted.")
print("Welcome to the system!")
else:
print("Access denied.")
print("Incorrect password.")8.3) Multiple Choices with if-elif-else
Real-world decisions often involve more than two options. Should we charge standard shipping, express shipping, or overnight shipping? Is a grade an A, B, C, D, or F? The if-elif-else chain handles multiple mutually exclusive alternatives.
8.3.1) The Structure of if-elif-else
Here's the syntax:
if condition1:
# Execute if condition1 is True
block1
elif condition2:
# Execute if condition1 is False and condition2 is True
block2
elif condition3:
# Execute if condition1 and condition2 are False, and condition3 is True
block3
else:
# Execute if all conditions are False
block4Key points about if-elif-else chains:
elifis short for "else if": It provides additional conditions to check- Order matters: Python checks conditions from top to bottom
- First match wins: Once a condition is
True, that block executes and the rest are skipped - Exactly one block executes: At most one block in the chain will run
elseis optional: It catches all cases not handled by previous conditions
Let's see a practical example:
# grade_calculator.py
score = int(input("Enter your exam score (0-100): "))
if score >= 90:
grade = "A"
print("Excellent work!")
elif score >= 80:
grade = "B"
print("Good job!")
elif score >= 70:
grade = "C"
print("Satisfactory.")
elif score >= 60:
grade = "D"
print("You passed, but consider reviewing the material.")
else:
grade = "F"
print("Unfortunately, you did not pass.")
print(f"Your grade is: {grade}")If you enter 85:
Good job!
Your grade is: BLet's trace through what happens:
- Check
score >= 90: False (85 is not >= 90), so skip this block - Check
score >= 80: True (85 >= 80), so execute this block - Skip all remaining
elifandelseblocks because we found a match
If you enter 55:
Unfortunately, you did not pass.
Your grade is: FAll conditions are False, so the else block executes.
8.3.2) Why Order Matters in elif Chains
The order of conditions is crucial because Python stops checking as soon as it finds a True condition. Consider this incorrect grading system:
# INCORRECT ORDER - Don't do this!
score = 85
if score >= 60: # This will match first!
grade = "D"
elif score >= 70:
grade = "C"
elif score >= 80:
grade = "B"
elif score >= 90:
grade = "A"
else:
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: DThis gives the wrong result! The score of 85 should be a B, but it gets a D because score >= 60 is checked first and is True. Python never reaches the score >= 80 condition.
Always order conditions from most specific to least specific:
# CORRECT ORDER
score = 85
if score >= 90: # Most specific
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else: # Least specific
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: B8.3.3) Using elif Without else
The else clause is optional. Sometimes you only want to handle specific cases and do nothing for others:
# weekend_checker.py
day = input("Enter a day of the week: ").lower()
if day == "saturday" or day == "sunday":
print("It's the weekend! Time to relax.")
elif day == "friday":
print("It's Friday! The weekend is almost here.")
elif day in ["monday", "tuesday", "wednesday", "thursday"]:
print("It's a weekday. Time to work or study.")
# No else clause - if none of these match, nothing happens
print("Have a great day!")If you enter "holiday":
Have a great day!No condition matched, and there's no else clause, so only the final print() executes.
8.4) Nested if Statements
Sometimes you need to make a decision within a decision. Nested if statements place one conditional inside another, allowing you to check additional conditions only after an initial condition is met.
8.4.1) Understanding Nested Conditionals
Nested if statements are powerful because they let you avoid checking conditions that don't make sense yet. For example, there's no point asking for a password if the user doesn't have an account. Nesting lets you structure your logic to match real-world decision-making processes where some questions only make sense after others are answered.
A nested if statement is simply an if statement (or if-elif-else chain) inside another if block:
if outer_condition:
# This code executes if outer_condition is True
if inner_condition:
# This code executes if BOTH conditions are True
inner_block
else:
# This executes if outer_condition is True but inner_condition is False
inner_else_block
else:
# This executes if outer_condition is False
outer_else_blockThe inner if statement only gets evaluated if the outer condition is True. This creates a hierarchy of decisions.
Here's a simple example:
# account_login.py
has_account = input("Do you have an account? (yes/no): ").lower() == "yes"
if has_account:
print("Welcome back!")
password = input("Enter your password: ")
if password == "secret123":
print("Login successful!")
print("Access granted to your dashboard.")
else:
print("Incorrect password.")
print("Access denied.")
else:
print("Please create an account first.")
print("Visit our registration page.")If you answer "yes" and enter the correct password:
Welcome back!
Login successful!
Access granted to your dashboard.If you answer "yes" but enter the wrong password:
Welcome back!
Incorrect password.
Access denied.If you answer "no":
Please create an account first.
Visit our registration page.Notice how the password check only happens if the user has an account. This is the key benefit of nesting—you can avoid unnecessary checks.
8.4.2) When to Use Nested if Statements
Nested if statements are useful when:
- Decisions depend on previous decisions: You need to check something only after another condition is met
- Creating decision trees: Each level narrows down the possibilities
- Validating prerequisites: Check basic requirements before checking detailed requirements
- Avoiding unnecessary checks: Skip expensive operations when earlier conditions fail
Example: Eligibility for a loan
# loan_eligibility.py
age = int(input("Enter your age: "))
if age >= 18:
print("Age requirement met.")
income = float(input("Enter your annual income: $"))
if income >= 30000:
print("Income requirement met.")
credit_score = int(input("Enter your credit score: "))
if credit_score >= 650:
print("Congratulations! You are eligible for a loan.")
print("Please proceed to the application form.")
else:
print("Sorry, your credit score is too low.")
print("Minimum required: 650")
else:
print("Sorry, your income is too low.")
print("Minimum required: $30,000")
else:
print("Sorry, you must be 18 or older to apply.")This creates a decision tree where each level depends on the previous one. If age is under 18, we never ask about income or credit score.
8.4.3) Avoiding Excessive Nesting
While nesting is powerful, too many levels make code hard to read and understand. Consider this deeply nested example:
# Too deeply nested - hard to follow
if condition1:
if condition2:
if condition3:
if condition4:
if condition5:
print("All conditions met!")This is difficult to read and maintain. Here are strategies to reduce nesting:
Strategy 1: Combine conditions when appropriate
We'll learn about the and operator in detail in Chapter 9, but for now, just know it lets you check multiple conditions at once:
# Better: Use 'and' to combine conditions (Chapter 9 will explain this fully)
# We'll learn about 'and' in Chapter 9, but for now, just know it checks
# that all conditions are true
if condition1 and condition2 and condition3 and condition4 and condition5:
print("All conditions met!")Strategy 2: Use early returns (when working with functions, which we'll learn in Chapter 19):
# In a function, we can return early
def check_eligibility(age, income, credit_score):
if age < 18:
return "Too young"
if income < 30000:
return "Income too low"
if credit_score < 650:
return "Credit score too low"
return "Eligible"Strategy 3: Flatten with elif when appropriate:
# Instead of nested ifs checking ranges
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
# ... and so on8.5) Common if Statement Pitfalls (Indentation, Colons, and Logic)
Even experienced programmers make mistakes with if statements. This section covers the most common errors beginners encounter and how to avoid them.
8.5.1) Indentation Errors
Python uses indentation to determine which statements belong to which block. Incorrect indentation is one of the most common sources of errors.
Problem 1: Missing indentation
# INCORRECT - IndentationError
age = 20
if age >= 18:
print("You are an adult.") # Not indented!This produces:
File "example.py", line 4
print("You are an adult.")
^
IndentationError: expected an indented blockSolution: Always indent the block under an if statement:
# CORRECT
age = 20
if age >= 18:
print("You are an adult.") # Properly indentedProblem 2: Inconsistent indentation
# INCORRECT - Mixing spaces and tabs, or inconsistent spaces
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # Extra spaces - inconsistent indentationSolution: Use consistent indentation (4 spaces is the Python standard):
# CORRECT
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # Same indentation levelProblem 3: Incorrect nesting indentation
# INCORRECT - Wrong indentation level
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # Should be indented moreSolution: Each nested level needs additional indentation:
# CORRECT
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # Properly indented for nested block8.5.2) Missing Colons
The colon (:) at the end of if, elif, and else lines is required. Forgetting it is a very common mistake:
# INCORRECT - SyntaxError: missing colon
if age >= 18
print("Adult")This produces:
File "example.py", line 2
if age >= 18
^
SyntaxError: invalid syntaxSolution: Always include the colon:
# CORRECT
if age >= 18:
print("Adult")The same applies to elif and else:
# CORRECT - All colons present
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "F"8.5.3) Incorrect Comparison Operators
Problem 1: Using assignment (=) instead of comparison (==)
# INCORRECT - This assigns 18 to age, doesn't compare!
age = 20
if age = 18: # SyntaxError
print("You are 18")Solution: Use == for comparison:
# CORRECT
age = 20
if age == 18:
print("You are 18")8.5.4) Unreachable Code Due to Logic Errors
Problem: Conditions that can never be True
# INCORRECT - The elif can never execute
score = 85
if score >= 60:
print("You passed!")
elif score >= 80: # This will never execute!
print("You got a B!")If score is 85, the first condition (score >= 60) is True, so the elif never gets checked. The order is wrong.
Solution: Order conditions from most specific to least specific:
# CORRECT
score = 85
if score >= 80:
print("You got a B!")
elif score >= 60:
print("You passed!")8.5.5) Empty if Blocks
You cannot have an empty if block in Python:
# INCORRECT - SyntaxError
if temperature > 30:
# I'll add code here later
print("Done")This produces:
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented blockSolution: Use the pass statement as a placeholder (covered in the next section):
# CORRECT - Using pass as a placeholder
if temperature > 30:
pass # TODO: Add code here later
print("Done")8.6) Using pass as a Placeholder in Blocks
Sometimes when writing code, you know you need an if statement but haven't decided what code should go in it yet. Python doesn't allow empty code blocks, so you need a way to create a valid but "do nothing" block. That's where the pass statement comes in.
8.6.1) What is pass?
The pass statement is a null operation—when Python executes it, nothing happens. It's a placeholder that allows you to write syntactically correct code even when you don't have the implementation ready yet.
if condition:
pass # Do nothing for nowThink of pass as a way to tell Python: "I know I need code here, but I'll fill it in later." It's particularly useful during development when you're sketching out the structure of your program.
8.6.2) Why pass is Necessary
Python requires at least one statement in every code block. An empty block causes a syntax error:
# INCORRECT - This causes an error
if age >= 18:
# TODO: Add adult logic here
print("Done")Error:
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented blockUsing pass makes the code syntactically valid:
# CORRECT - Using pass as a placeholder
if age >= 18:
pass # TODO: Add adult logic here
print("Done")8.6.3) Common Uses of pass
Use 1: Placeholder during development
When you're outlining your program's structure but haven't implemented everything yet:
# user_system.py
user_type = input("Enter user type (admin/user/guest): ").lower()
if user_type == "admin":
pass # TODO: Implement admin features
elif user_type == "user":
pass # TODO: Implement user features
elif user_type == "guest":
print("Welcome, guest! Limited access granted.")
else:
print("Invalid user type.")This lets you run the program and test the parts you have implemented while leaving placeholders for future work.
Use 2: Intentionally doing nothing in one branch
Sometimes you genuinely want to do nothing in certain cases but need to handle other cases:
# positive_numbers.py
# Only process positive numbers
number = int(input("Enter a number: "))
if number > 0:
result = number * 2
print(f"Double of {number} is {result}")
elif number == 0:
pass # Zero is valid but requires no action
else:
print("Negative numbers are not allowed.")8.6.4) pass in Other Contexts
While we've focused on pass in if statements, you'll encounter it in other contexts as you learn more Python:
- Functions (Chapter 20): Placeholder for function bodies
- Classes (Chapter 31): Placeholder for class definitions
- Loops (Chapters 11-12): Placeholder for loop bodies
- Exception handlers (Chapter 29): Intentionally ignoring errors
For now, remember that pass is your tool for creating valid but empty code blocks when you need them.
Bringing It All Together
In this chapter, you've learned how to make your programs intelligent and responsive by using conditional statements. Let's review the key concepts:
Simple if statements execute code only when a condition is true:
if temperature > 30:
print("It's hot outside!")if-else statements choose between two alternatives:
if age >= 18:
print("Adult")
else:
print("Minor")if-elif-else chains handle multiple mutually exclusive options:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"Nested if statements make decisions within decisions:
if has_account:
if password_correct:
print("Welcome!")
else:
print("Wrong password")
else:
print("Create an account")Common pitfalls to avoid:
- Missing colons after
if,elif, andelse - Incorrect or inconsistent indentation
- Using
=instead of==for comparison - Wrong order in
elifchains - Empty blocks without
pass
The pass statement serves as a placeholder for empty blocks during development.
You now have the tools to write programs that make intelligent decisions based on conditions. In the next chapter, we'll learn about boolean logic operators (and, or, not) that let you combine multiple conditions into more sophisticated decision-making logic. This will make your if statements even more powerful and expressive.