🐍 2. More Conditionals - Advanced Course in Programming
Chapter Overview
Welcome to Part 2, Chapter 2 of our Advanced Course in Programming! This module builds upon the basic conditional statements you learned in the Introduction to Programming course. We'll explore more complex conditional logic, including nested conditionals, multiple conditions, and advanced boolean operations that allow you to create sophisticated decision-making programs.
By the end of this chapter, you'll be able to write programs that make complex decisions, handle multiple scenarios, and create more intelligent applications that can respond appropriately to various inputs and conditions.
2.1 Review of Basic Conditionals
Quick Recap of if Statements
Before diving into advanced conditionals, let's quickly review the basic conditional structure:
# Basic if statement
if condition:
# Code to execute if condition is True
statement1
statement2
# if-else statement
if condition:
# Code for True condition
statement1
else:
# Code for False condition
statement2
# if-elif-else statement
if condition1:
# Code for condition1
statement1
elif condition2:
# Code for condition2
statement2
else:
# Code for all other cases
statement3
2.2 Nested If Statements
What Are Nested Conditionals?
Building Complex Decision Trees
Nested if statements occur when you place one if statement inside another. This allows you to check multiple conditions in a hierarchical manner. The inner if statement is only executed if the outer condition is True.
# Basic nested if structure
if outer_condition:
# This code runs if outer_condition is True
print("Outer condition is met")
if inner_condition:
# This code only runs if BOTH outer AND inner conditions are True
print("Inner condition is also met")
else:
# This code runs if outer is True but inner is False
print("Outer is true, but inner is false")
else:
# This code runs if outer_condition is False
print("Outer condition is not met")
Practical Example: Grade Classification
1Simple Grade Classification
# Grade classification using nested if statements
score = 85
if score >= 60:
print("You passed!")
if score >= 90:
print("Excellent! You got an A!")
elif score >= 80:
print("Great job! You got a B!")
elif score >= 70:
print("Good work! You got a C!")
else:
print("You got a D. Keep trying!")
else:
print("You failed. Better luck next time!")
if score >= 50:
print("You were close! Just a few more points needed.")
else:
print("You need to study much harder.")
Real-World Example: User Authentication
2User Login System
# Simulated user authentication system
def authenticate_user(username, password):
"""
Authenticate a user with nested conditional checks.
In a real system, this would check against a database.
"""
# Check if username exists
if username == "admin":
# Username exists, now check password
if password == "secret123":
print("Welcome, Administrator!")
print("You have full access to the system.")
return True
else:
print("Incorrect password for admin account.")
return False
elif username == "user":
# Username exists, check password
if password == "password":
print("Welcome, User!")
print("You have limited access.")
return True
else:
print("Incorrect password for user account.")
return False
else:
# Username doesn't exist
print("User account not found.")
print("Please check your username or register a new account.")
return False
# Test the function
print("Testing authentication:")
authenticate_user("admin", "secret123")
print()
authenticate_user("admin", "wrongpass")
print()
authenticate_user("unknown", "password")
Common Pitfalls with Nested Conditionals
❌ Poor Indentation
# WRONG - indentation problem
if x > 5:
print("x is greater than 5")
if y > 10: # This is not nested!
print("y is greater than 10")
✅ Correct Nesting
# CORRECT - properly nested
if x > 5:
print("x is greater than 5")
if y > 10:
print("y is greater than 10")
2.3 Multiple Conditions with Logical Operators
Logical Operators in Python
The Three Logical Operators
Python provides three logical operators to combine multiple conditions:
| Operator |
Description |
Example |
Result |
and |
True if both conditions are True |
True and False |
False |
or |
True if at least one condition is True |
True or False |
True |
not |
Reverses the truth value |
not True |
False |
Truth Tables
🔗 AND Operator Truth Table
| A |
B |
A and B |
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
🔄 OR Operator Truth Table
| A |
B |
A or B |
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
🚫 NOT Operator
| A |
not A |
| True | False |
| False | True |
Practical Examples with Logical Operators
3Age Verification System
# Age verification with multiple conditions
def check_age_category(age, has_permission=False):
"""
Determine age category with special permissions.
"""
if age >= 18 and has_permission:
print("Adult with special permission - Full access granted")
elif age >= 18:
print("Adult - Standard access granted")
elif age >= 13 and age < 18:
print("Teenager - Limited access")
elif age >= 5 and age < 13:
print("Child - Supervised access only")
else:
print("Too young - Access denied")
# Test different scenarios
print("Age 25, no permission:")
check_age_category(25, False)
print("\nAge 25, with permission:")
check_age_category(25, True)
print("\nAge 15:")
check_age_category(15)
print("\nAge 8:")
check_age_category(8)
4Weather Advisory System
def weather_advisory(temperature, humidity, wind_speed):
"""
Provide weather advisories based on multiple conditions.
"""
# Check for dangerous conditions
if temperature > 35 or (temperature > 30 and humidity > 80):
print("🔥 HEAT WARNING: Stay hydrated and avoid outdoor activities")
if wind_speed > 50 or (wind_speed > 30 and humidity < 30):
print("💨 WIND WARNING: Secure loose objects")
# Check for comfortable conditions
if temperature >= 20 and temperature <= 25 and humidity >= 40 and humidity <= 60:
print("✅ Perfect weather conditions!")
# Check for multiple warnings
severe_conditions = (temperature > 35 and wind_speed > 40) or (humidity > 90 and wind_speed > 20)
if severe_conditions:
print("🚨 SEVERE WEATHER ALERT: Take immediate precautions!")
# Test the weather system
print("Hot and humid day:")
weather_advisory(32, 85, 15)
print("\nPerfect weather:")
weather_advisory(22, 50, 10)
print("\nStorm conditions:")
weather_advisory(28, 95, 45)
2.4 Complex Conditional Expressions
Combining Multiple Operators
Building Complex Logic
You can combine multiple logical operators to create sophisticated conditions. Remember the order of precedence:
- Arithmetic operators (+, -, *, /, etc.)
- Comparison operators (==, !=, <, >, etc.)
- Logical operators (not, and, or)
⚠️ Logical Operator Precedence
not has higher precedence than and, which has higher precedence than or. Use parentheses to make complex expressions clear.
Advanced Examples
5Student Grade Calculator
def calculate_final_grade(homework_avg, exam_score, participation_score):
"""
Calculate final grade based on multiple criteria.
"""
# Weighted average: 40% homework, 50% exam, 10% participation
final_score = (homework_avg * 0.4) + (exam_score * 0.5) + (participation_score * 0.1)
# Complex conditional for grade assignment
if final_score >= 90 and exam_score >= 80:
grade = "A"
message = "Outstanding performance!"
elif final_score >= 80 and (exam_score >= 70 or participation_score >= 90):
grade = "B"
message = "Good work!"
elif final_score >= 70 and not (exam_score < 60 and homework_avg < 70):
grade = "C"
message = "Satisfactory performance"
elif final_score >= 60 or (homework_avg >= 75 and participation_score >= 80):
grade = "D"
message = "Below average, needs improvement"
else:
grade = "F"
message = "Failed - must retake course"
return grade, final_score, message
# Test the grade calculator
test_cases = [
(95, 88, 92), # Excellent student
(78, 82, 85), # Good student with high participation
(72, 68, 75), # Average student
(65, 58, 88), # Student saved by participation
(45, 52, 60) # Failing student
]
for homework, exam, participation in test_cases:
grade, score, message = calculate_final_grade(homework, exam, participation)
print(f"Homework: {homework}, Exam: {exam}, Participation: {participation}")
print(f"Final Score: {score:.1f}, Grade: {grade} - {message}")
print()
Short-Circuit Evaluation
Efficient Boolean Evaluation
Python uses short-circuit evaluation for logical operators. This means:
- AND: If the first operand is False, the second isn't evaluated
- OR: If the first operand is True, the second isn't evaluated
# Short-circuit with AND
def check_division(x, y):
# If y is 0, the first condition fails and second isn't evaluated
if y != 0 and x / y > 2:
print(f"x/y = {x/y} which is greater than 2")
else:
print("Cannot divide by zero or result is not > 2")
# Short-circuit with OR
def get_user_input_or_default():
user_input = input("Enter a value (or press Enter for default): ")
# If user_input is truthy (not empty), use it; otherwise use default
result = user_input or "default_value"
return result
check_division(10, 5) # Will print the result
check_division(10, 0) # Will not crash due to short-circuit
2.5 Conditional Expressions (Ternary Operator)
Compact Conditional Logic
Python's Ternary Operator
Python supports conditional expressions (also called ternary operators) for compact conditional logic:
# Syntax: value_if_true if condition else value_if_false
# Traditional if-else
x = 10
if x > 5:
result = "big"
else:
result = "small"
print(result) # "big"
# Conditional expression (ternary)
result = "big" if x > 5 else "small"
print(result) # "big"
# More complex example
age = 25
status = "adult" if age >= 18 else "minor"
print(f"Age {age}: {status}")
# Nested ternary (use with caution!)
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))
print(f"Score {score}: Grade {grade}")
2.6 Best Practices for Complex Conditionals
Improving Code Readability
📖 Use Descriptive Variable Names
# ❌ Hard to read
if x > 10 and y < 5 or z == 0:
pass
# ✅ Self-documenting
age_valid = age >= 18 and age <= 65
score_good = exam_score >= 70
has_permission = user_role == "admin"
if age_valid and (score_good or has_permission):
grant_access()
🔧 Extract Complex Conditions
# ❌ Complex nested conditions
if user.is_authenticated() and (user.has_permission('edit') or user.is_admin()) and not user.is_suspended():
# ✅ Extract to function
def can_edit_content(user):
if not user.is_authenticated():
return False
if user.is_suspended():
return False
if user.has_permission('edit') or user.is_admin():
return True
return False
if can_edit_content(user):
# Edit content
📋 Use Parentheses for Clarity
# Use parentheses to group related conditions
if (age >= 18 and has_id) or (age >= 16 and has_parent_consent):
enter_venue()
# Avoid overly complex single lines
if (temperature > 30 and humidity > 70) or (wind_speed > 40 and temperature < 0):
issue_weather_warning()
2.7 Practical Exercises
Exercise 2.1: Smart Door Lock System
🔐 Create a Security System
Write a program that simulates a smart door lock with multiple access conditions:
- Valid RFID card OR correct PIN
- Time must be between 6 AM and 10 PM
- Door must not be already locked
- Emergency override for admin codes
def check_access(rfid_present, pin_entered, current_hour, door_locked, admin_code=None):
"""
Check if access should be granted to the smart door lock.
"""
# Define valid credentials
valid_rfids = ["ABC123", "DEF456", "GHI789"]
valid_pins = ["1234", "5678", "9012"]
admin_codes = ["ADMIN001", "ADMIN002"]
# Check time restrictions (6 AM to 10 PM)
time_valid = 6 <= current_hour <= 22
if not time_valid:
return False, "Access denied: Outside operating hours (6 AM - 10 PM)"
if door_locked:
return False, "Access denied: Door is already locked"
# Check access credentials
rfid_valid = rfid_present in valid_rfids
pin_valid = pin_entered in valid_pins
admin_valid = admin_code in admin_codes if admin_code else False
# Grant access if: valid credentials OR admin override
if (rfid_valid or pin_valid) or admin_valid:
if admin_valid:
message = "Admin access granted - Security override"
elif rfid_valid and pin_valid:
message = "Access granted: RFID and PIN verified"
elif rfid_valid:
message = "Access granted: RFID verified"
else:
message = "Access granted: PIN verified"
return True, message
else:
return False, "Access denied: Invalid credentials"
# Test the access system
test_cases = [
("ABC123", "9999", 14, False, None), # Valid RFID, invalid PIN
("INVALID", "1234", 14, False, None), # Invalid RFID, valid PIN
("ABC123", "1234", 2, False, None), # Valid credentials, wrong time
("ABC123", "1234", 14, True, None), # Valid credentials, door locked
("INVALID", "9999", 14, False, "ADMIN001"), # Invalid credentials, admin override
]
for rfid, pin, hour, locked, admin in test_cases:
access_granted, message = check_access(rfid, pin, hour, locked, admin)
status = "✅" if access_granted else "❌"
print(f"{status} RFID: {rfid}, PIN: {pin}, Hour: {hour}, Locked: {locked}, Admin: {admin}")
print(f" {message}")
print()
💻 Exercise 2.2: Loan Approval System
Create a loan approval system with multiple criteria:
- Credit score ≥ 650
- Income ≥ $25,000/year OR down payment ≥ 20%
- Employment status: Employed OR Student with cosigner
- Debt-to-income ratio ≤ 40%
def approve_loan(credit_score, annual_income, down_payment_percent,
employment_status, debt_to_income_ratio, has_cosigner=False):
"""
Determine if a loan application should be approved.
"""
# Credit score requirement
credit_ok = credit_score >= 650
# Income/down payment requirements
income_ok = annual_income >= 25000
down_payment_ok = down_payment_percent >= 20
financial_ok = income_ok or down_payment_ok
# Employment requirements
employment_ok = (employment_status == "employed" or
(employment_status == "student" and has_cosigner))
# Debt-to-income ratio
dti_ok = debt_to_income_ratio <= 0.40
# Overall approval
approved = credit_ok and financial_ok and employment_ok and dti_ok
# Determine approval reason or rejection reasons
if approved:
if credit_score >= 750 and down_payment_percent >= 25:
reason = "Approved - Premium terms available"
elif credit_score >= 700:
reason = "Approved - Standard terms"
else:
reason = "Approved - Conditional terms apply"
else:
reasons = []
if not credit_ok:
reasons.append(f"Credit score too low ({credit_score} < 650)")
if not financial_ok:
reasons.append("Income too low and insufficient down payment")
if not employment_ok:
reasons.append("Employment requirements not met")
if not dti_ok:
reasons.append(f"Debt-to-income ratio too high ({debt_to_income_ratio:.1%} > 40%)")
reason = "Rejected: " + ", ".join(reasons)
return approved, reason
# Test cases
applications = [
(720, 45000, 15, "employed", 0.25, False), # Should approve
(600, 30000, 25, "employed", 0.35, False), # Good down payment saves it
(680, 20000, 10, "student", 0.20, True), # Cosigner helps student
(550, 60000, 5, "employed", 0.50, False), # Credit score too low
(700, 15000, 5, "student", 0.30, False), # Student without cosigner
(780, 35000, 30, "employed", 0.45, False), # High DTI ratio
]
for app in applications:
credit, income, down_payment, emp_status, dti, cosigner = app
approved, reason = approve_loan(credit, income, down_payment,
emp_status, dti, cosigner)
status = "✅ APPROVED" if approved else "❌ REJECTED"
print(f"{status}: Credit {credit}, Income ${income}, Down {down_payment}%, Status {emp_status}, DTI {dti:.1%}")
print(f" {reason}")
print()
Knowledge Check
🧠 True or False Questions
1. In nested if statements, the inner if is only executed if the outer condition is True.
2. The 'and' operator returns True only if both operands are True.
3. Python uses short-circuit evaluation for logical operators.
4. You cannot use multiple elif statements in a single conditional block.
5. The 'not' operator has higher precedence than 'and'.
✅ Answers
1. True - The inner if statement is nested inside the outer if block
2. True - 'and' requires both conditions to be True
3. True - Python stops evaluating as soon as the result is determined
4. False - You can use as many elif statements as needed
5. True - Operator precedence: not > and > or
Chapter Summary
Key Concepts Learned
- Nested if statements: Placing conditionals inside other conditionals for complex logic
- Logical operators: and, or, not for combining multiple conditions
- Truth tables: Understanding how logical operators work
- Short-circuit evaluation: How Python optimizes conditional evaluation
- Complex expressions: Building sophisticated decision logic
- Ternary operators: Compact conditional expressions
- Best practices: Writing readable and maintainable conditional code
- Real-world applications: Authentication systems, loan approvals, weather advisories
Best Practices for Advanced Conditionals
- Use parentheses to clarify complex expressions
- Extract complex conditions into well-named variables or functions
- Use short-circuit evaluation to prevent errors
- Limit nesting to 2-3 levels for readability
- Consider using ternary operators for simple cases
- Test edge cases thoroughly
- Document complex logic with comments
🎯 Next Steps
In the next chapter, you'll learn about combining multiple conditions using advanced boolean logic and creating even more sophisticated decision-making structures. These skills will enable you to write programs that can handle complex real-world scenarios with multiple interdependent conditions.