🐍 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
TrueTrueTrue
TrueFalseFalse
FalseTrueFalse
FalseFalseFalse

🔄 OR Operator Truth Table

A B A or B
TrueTrueTrue
TrueFalseTrue
FalseTrueTrue
FalseFalseFalse

🚫 NOT Operator

A not A
TrueFalse
FalseTrue

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:

  1. Arithmetic operators (+, -, *, /, etc.)
  2. Comparison operators (==, !=, <, >, etc.)
  3. 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:

# 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:

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:

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

Best Practices for Advanced Conditionals

🎯 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.