Nested If Statements in Python
Table of Contents
1. [Introduction](#introduction) 2. [Basic Syntax](#basic-syntax) 3. [Understanding Nested If Structure](#understanding-nested-if-structure) 4. [Examples and Implementation](#examples-and-implementation) 5. [Best Practices](#best-practices) 6. [Common Patterns](#common-patterns) 7. [Performance Considerations](#performance-considerations) 8. [Alternatives to Nested If](#alternatives-to-nested-if) 9. [Debugging Nested If Statements](#debugging-nested-if-statements) 10. [Real-World Applications](#real-world-applications)Introduction
Nested if statements are conditional statements placed inside other conditional statements. This programming construct allows developers to create complex decision-making logic by testing multiple conditions in a hierarchical manner. When one condition is met, the program can then evaluate additional conditions within that branch of execution.
The concept of nesting enables programmers to build sophisticated control flow structures that can handle multiple scenarios and edge cases. Understanding nested if statements is crucial for developing robust applications that require complex decision-making processes.
Basic Syntax
The fundamental syntax for nested if statements follows Python's standard indentation rules. Each level of nesting requires additional indentation to maintain code readability and proper execution flow.
`python
if condition1:
# Code block for condition1
if condition2:
# Code block for condition1 and condition2
if condition3:
# Code block for all three conditions
else:
# Code block when condition3 is False
else:
# Code block when condition2 is False
else:
# Code block when condition1 is False
`
Indentation Rules
Python uses indentation to define code blocks, making proper spacing critical for nested structures:
| Nesting Level | Indentation Spaces | Description | |---------------|-------------------|-------------| | Level 0 | 0 spaces | Main program level | | Level 1 | 4 spaces | First nested level | | Level 2 | 8 spaces | Second nested level | | Level 3 | 12 spaces | Third nested level | | Level 4+ | 16+ spaces | Additional nesting levels |
Understanding Nested If Structure
Execution Flow
The execution of nested if statements follows a top-down approach where each condition is evaluated sequentially. When a condition evaluates to True, the program enters that code block and continues evaluating any nested conditions within it.
`python
Example demonstrating execution flow
def check_eligibility(age, income, credit_score): if age >= 18: print("Age requirement met") if income >= 30000: print("Income requirement met") if credit_score >= 650: print("Credit score requirement met") return "Approved" else: print("Credit score too low") return "Rejected - Credit Score" else: print("Income too low") return "Rejected - Income" else: print("Age requirement not met") return "Rejected - Age"Test the function
result = check_eligibility(25, 45000, 700) print(f"Final result: {result}")`Logical Operators vs Nested If
Understanding when to use nested if statements versus logical operators is essential for writing clean, maintainable code.
| Approach | Use Case | Example |
|----------|----------|---------|
| Nested If | Complex logic with different actions | Multiple validation steps |
| Logical Operators | Simple boolean combinations | if age >= 18 and income >= 30000: |
| Mixed Approach | Combination of both | Complex business rules |
Examples and Implementation
Example 1: Grade Classification System
`python
def classify_grade(score):
"""
Classify student grades based on score ranges with additional criteria
"""
if score >= 0 and score <= 100:
if score >= 90:
if score >= 97:
return "A+ (Excellent)"
elif score >= 93:
return "A (Outstanding)"
else:
return "A- (Very Good)"
elif score >= 80:
if score >= 87:
return "B+ (Good)"
elif score >= 83:
return "B (Above Average)"
else:
return "B- (Satisfactory)"
elif score >= 70:
if score >= 77:
return "C+ (Fair)"
elif score >= 73:
return "C (Below Average)"
else:
return "C- (Poor)"
elif score >= 60:
return "D (Failing)"
else:
return "F (Fail)"
else:
return "Invalid score range"
Test cases
test_scores = [95, 85, 75, 65, 55, 105, -5] for score in test_scores: print(f"Score: {score} -> Grade: {classify_grade(score)}")`Example 2: User Authentication System
`python
class UserAuthenticator:
def __init__(self):
self.users = {
"admin": {"password": "admin123", "role": "administrator", "active": True},
"user1": {"password": "pass123", "role": "user", "active": True},
"user2": {"password": "mypass", "role": "user", "active": False}
}
self.max_attempts = 3
self.login_attempts = {}
def authenticate(self, username, password):
"""
Authenticate user with nested validation checks
"""
if username in self.users:
# Check if account is locked due to failed attempts
if username in self.login_attempts:
if self.login_attempts[username] >= self.max_attempts:
return {
"status": "failed",
"message": "Account locked due to multiple failed attempts"
}
# Check if account is active
if self.users[username]["active"]:
# Verify password
if self.users[username]["password"] == password:
# Reset login attempts on successful login
if username in self.login_attempts:
del self.login_attempts[username]
# Check user role for additional permissions
if self.users[username]["role"] == "administrator":
return {
"status": "success",
"message": "Administrator login successful",
"permissions": ["read", "write", "delete", "admin"]
}
else:
return {
"status": "success",
"message": "User login successful",
"permissions": ["read", "write"]
}
else:
# Increment failed attempts
if username not in self.login_attempts:
self.login_attempts[username] = 1
else:
self.login_attempts[username] += 1
remaining = self.max_attempts - self.login_attempts[username]
if remaining > 0:
return {
"status": "failed",
"message": f"Invalid password. {remaining} attempts remaining"
}
else:
return {
"status": "failed",
"message": "Account locked due to multiple failed attempts"
}
else:
return {
"status": "failed",
"message": "Account is deactivated"
}
else:
return {
"status": "failed",
"message": "Username not found"
}
Usage example
auth = UserAuthenticator() test_cases = [ ("admin", "admin123"), ("user1", "wrongpass"), ("user1", "pass123"), ("user2", "mypass"), ("nonexistent", "anypass") ]for username, password in test_cases:
result = auth.authenticate(username, password)
print(f"Login attempt - User: {username}, Result: {result}")
`
Example 3: Weather Advisory System
`python
def weather_advisory(temperature, humidity, wind_speed, precipitation):
"""
Generate weather advisories based on multiple conditions
"""
advisories = []
# Temperature-based advisories
if temperature > 35: # Hot weather
if humidity > 70:
if wind_speed < 5:
advisories.append("EXTREME HEAT WARNING: High temperature with high humidity and low wind")
else:
advisories.append("HEAT WARNING: High temperature and humidity, but wind provides some relief")
else:
if wind_speed < 10:
advisories.append("HOT WEATHER ADVISORY: High temperature with low humidity")
else:
advisories.append("WARM WEATHER: High temperature but manageable conditions")
elif temperature < 0: # Cold weather
if wind_speed > 20:
if humidity > 60:
advisories.append("SEVERE WINTER WARNING: Freezing temperature with strong winds and high humidity")
else:
advisories.append("WINTER STORM WARNING: Freezing temperature with strong winds")
else:
if humidity > 80:
advisories.append("COLD WEATHER WARNING: Freezing temperature with high humidity")
else:
advisories.append("COLD WEATHER ADVISORY: Below freezing temperature")
# Precipitation-based advisories
if precipitation > 0:
if temperature <= 0:
if precipitation > 10:
advisories.append("HEAVY SNOW WARNING: Significant snowfall expected")
else:
advisories.append("SNOW ADVISORY: Light to moderate snowfall")
else:
if precipitation > 25:
if wind_speed > 15:
advisories.append("SEVERE THUNDERSTORM WARNING: Heavy rain with strong winds")
else:
advisories.append("HEAVY RAIN WARNING: Significant rainfall expected")
elif precipitation > 10:
advisories.append("RAIN ADVISORY: Moderate rainfall expected")
# Wind-specific advisories
if wind_speed > 30:
if temperature > 30:
advisories.append("HOT WIND WARNING: Strong winds with high temperature")
elif temperature < 5:
advisories.append("WIND CHILL WARNING: Strong cold winds")
else:
advisories.append("HIGH WIND WARNING: Strong winds expected")
return advisories if advisories else ["NORMAL WEATHER CONDITIONS"]
Test different weather scenarios
weather_scenarios = [ {"temp": 38, "humidity": 75, "wind": 3, "precip": 0}, {"temp": -5, "humidity": 65, "wind": 25, "precip": 15}, {"temp": 25, "humidity": 45, "wind": 12, "precip": 30}, {"temp": 20, "humidity": 50, "wind": 8, "precip": 0} ]for i, weather in enumerate(weather_scenarios, 1):
print(f"\nScenario {i}:")
print(f"Temperature: {weather['temp']}°C, Humidity: {weather['humidity']}%")
print(f"Wind Speed: {weather['wind']} km/h, Precipitation: {weather['precip']} mm")
advisories = weather_advisory(weather['temp'], weather['humidity'],
weather['wind'], weather['precip'])
for advisory in advisories:
print(f"- {advisory}")
`
Best Practices
Code Readability and Maintainability
| Practice | Description | Example |
|----------|-------------|---------|
| Limit Nesting Depth | Avoid more than 3-4 levels of nesting | Use early returns or helper functions |
| Use Descriptive Variable Names | Clear variable names improve understanding | is_valid_user instead of flag |
| Add Comments | Document complex logic | Explain business rules |
| Consistent Indentation | Use 4 spaces consistently | Follow PEP 8 guidelines |
Early Return Pattern
`python
Instead of deep nesting
def process_order_bad(order): if order is not None: if order.items: if order.customer.is_verified: if order.payment.is_valid: if order.inventory_available(): return process_payment(order) else: return "Inventory unavailable" else: return "Invalid payment" else: return "Customer not verified" else: return "No items in order" else: return "Order is None"Better approach with early returns
def process_order_good(order): if order is None: return "Order is None" if not order.items: return "No items in order" if not order.customer.is_verified: return "Customer not verified" if not order.payment.is_valid: return "Invalid payment" if not order.inventory_available(): return "Inventory unavailable" return process_payment(order)`Function Decomposition
`python
Breaking complex nested logic into smaller functions
def validate_user_input(data): """Main validation function that orchestrates all checks""" if not is_data_present(data): return False, "No data provided" if not is_format_valid(data): return False, "Invalid data format" if not is_content_valid(data): return False, "Invalid data content" return True, "Valid data"def is_data_present(data): """Check if data exists and is not empty""" return data is not None and len(data) > 0
def is_format_valid(data): """Validate data format""" if isinstance(data, dict): required_fields = ['name', 'email', 'age'] return all(field in data for field in required_fields) return False
def is_content_valid(data):
"""Validate data content"""
if not data.get('name', '').strip():
return False
if '@' not in data.get('email', ''):
return False
age = data.get('age', 0)
if not isinstance(age, int) or age < 0 or age > 150:
return False
return True
`
Common Patterns
Pattern 1: Input Validation Cascade
`python
def validate_registration_data(data):
"""
Validate user registration data with cascading checks
"""
validation_results = {
'is_valid': False,
'errors': [],
'warnings': []
}
# Check if data exists
if not data:
validation_results['errors'].append("No registration data provided")
return validation_results
# Validate username
if 'username' in data:
username = data['username']
if len(username) >= 3:
if username.isalnum():
if not username.isdigit():
# Username is valid
pass
else:
validation_results['errors'].append("Username cannot be only numbers")
else:
validation_results['errors'].append("Username must contain only letters and numbers")
else:
validation_results['errors'].append("Username must be at least 3 characters long")
else:
validation_results['errors'].append("Username is required")
# Validate email
if 'email' in data:
email = data['email']
if '@' in email:
if '.' in email.split('@')[1]:
if not email.startswith('@') and not email.endswith('@'):
# Email format is acceptable
pass
else:
validation_results['errors'].append("Invalid email format")
else:
validation_results['errors'].append("Email domain must contain a dot")
else:
validation_results['errors'].append("Email must contain @ symbol")
else:
validation_results['errors'].append("Email is required")
# Validate password
if 'password' in data:
password = data['password']
if len(password) >= 8:
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
if has_upper:
if has_lower:
if has_digit:
# Password meets all requirements
pass
else:
validation_results['warnings'].append("Password should contain at least one digit")
else:
validation_results['errors'].append("Password must contain lowercase letters")
else:
validation_results['errors'].append("Password must contain uppercase letters")
else:
validation_results['errors'].append("Password must be at least 8 characters long")
else:
validation_results['errors'].append("Password is required")
# Set overall validation status
validation_results['is_valid'] = len(validation_results['errors']) == 0
return validation_results
Test the validation function
test_data = { 'username': 'john123', 'email': 'john@example.com', 'password': 'MyPassword123' }result = validate_registration_data(test_data)
print(f"Validation Result: {result}")
`
Pattern 2: Configuration-Based Decision Making
`python
class AccessControlSystem:
def __init__(self):
self.permissions = {
'admin': {
'resources': ['users', 'settings', 'reports', 'system'],
'actions': ['create', 'read', 'update', 'delete'],
'time_restrictions': False,
'ip_restrictions': False
},
'manager': {
'resources': ['users', 'reports'],
'actions': ['create', 'read', 'update'],
'time_restrictions': True,
'allowed_hours': (8, 18),
'ip_restrictions': True,
'allowed_ips': ['192.168.1.0/24']
},
'user': {
'resources': ['profile'],
'actions': ['read', 'update'],
'time_restrictions': True,
'allowed_hours': (6, 22),
'ip_restrictions': False
}
}
def check_access(self, user_role, resource, action, current_hour=None, user_ip=None):
"""
Check if user has access to perform action on resource
"""
if user_role not in self.permissions:
return {
'allowed': False,
'reason': 'Invalid user role'
}
role_config = self.permissions[user_role]
# Check resource access
if resource in role_config['resources']:
# Check action permission
if action in role_config['actions']:
# Check time restrictions
if role_config.get('time_restrictions', False):
if current_hour is not None:
allowed_hours = role_config.get('allowed_hours', (0, 23))
if allowed_hours[0] <= current_hour <= allowed_hours[1]:
# Time check passed, now check IP restrictions
if role_config.get('ip_restrictions', False):
if user_ip is not None:
allowed_ips = role_config.get('allowed_ips', [])
if self._is_ip_allowed(user_ip, allowed_ips):
return {
'allowed': True,
'reason': 'Access granted'
}
else:
return {
'allowed': False,
'reason': 'IP address not allowed'
}
else:
return {
'allowed': False,
'reason': 'IP address required for verification'
}
else:
return {
'allowed': True,
'reason': 'Access granted'
}
else:
return {
'allowed': False,
'reason': f'Access only allowed between {allowed_hours[0]}:00 and {allowed_hours[1]}:00'
}
else:
return {
'allowed': False,
'reason': 'Current time required for verification'
}
else:
# No time restrictions
if role_config.get('ip_restrictions', False):
if user_ip is not None:
allowed_ips = role_config.get('allowed_ips', [])
if self._is_ip_allowed(user_ip, allowed_ips):
return {
'allowed': True,
'reason': 'Access granted'
}
else:
return {
'allowed': False,
'reason': 'IP address not allowed'
}
else:
return {
'allowed': False,
'reason': 'IP address required for verification'
}
else:
return {
'allowed': True,
'reason': 'Access granted'
}
else:
return {
'allowed': False,
'reason': f'Action "{action}" not permitted for this role'
}
else:
return {
'allowed': False,
'reason': f'Resource "{resource}" not accessible for this role'
}
def _is_ip_allowed(self, user_ip, allowed_ips):
"""Simple IP checking (in real implementation, use proper IP address libraries)"""
for allowed_ip in allowed_ips:
if allowed_ip.endswith('/24'):
network = allowed_ip[:-3]
if user_ip.startswith(network[:-1]):
return True
elif user_ip == allowed_ip:
return True
return False
Usage example
access_control = AccessControlSystem()test_scenarios = [ {'role': 'admin', 'resource': 'system', 'action': 'delete', 'hour': 14, 'ip': '10.0.0.1'}, {'role': 'manager', 'resource': 'users', 'action': 'create', 'hour': 10, 'ip': '192.168.1.50'}, {'role': 'manager', 'resource': 'users', 'action': 'create', 'hour': 20, 'ip': '192.168.1.50'}, {'role': 'user', 'resource': 'profile', 'action': 'update', 'hour': 15, 'ip': None}, {'role': 'user', 'resource': 'settings', 'action': 'read', 'hour': 15, 'ip': None} ]
for scenario in test_scenarios:
result = access_control.check_access(
scenario['role'],
scenario['resource'],
scenario['action'],
scenario.get('hour'),
scenario.get('ip')
)
print(f"Role: {scenario['role']}, Resource: {scenario['resource']}, Action: {scenario['action']}")
print(f"Result: {result['allowed']}, Reason: {result['reason']}\n")
`
Performance Considerations
Optimization Strategies
| Strategy | Description | Performance Impact | |----------|-------------|-------------------| | Short-circuit Evaluation | Place most likely conditions first | Reduces unnecessary evaluations | | Condition Reordering | Order by probability and cost | Improves average case performance | | Caching Results | Store expensive computations | Reduces redundant calculations | | Early Termination | Return immediately when possible | Prevents deep nesting execution |
Example: Optimized Nested Conditions
`python
import time
from functools import lru_cache
class OptimizedValidator: def __init__(self): self.cache_hits = 0 self.cache_misses = 0 @lru_cache(maxsize=128) def expensive_validation(self, data): """Simulate an expensive validation operation""" time.sleep(0.1) # Simulate network call or complex computation return len(data) > 10 and data.isalnum() def validate_optimized(self, user_data): """ Optimized validation with strategic condition ordering """ # Quick checks first (most likely to fail, least expensive) if not user_data: # Most common failure case return False, "No data provided" if len(user_data) < 3: # Quick length check return False, "Data too short" # Medium cost checks if not isinstance(user_data, str): # Type check return False, "Data must be string" # Expensive checks last (cached for performance) if not self.expensive_validation(user_data): self.cache_misses += 1 return False, "Failed expensive validation" self.cache_hits += 1 return True, "Validation successful" def validate_unoptimized(self, user_data): """ Unoptimized version for comparison """ # Expensive check first (poor performance) if user_data and isinstance(user_data, str): if self.expensive_validation(user_data): if len(user_data) >= 3: return True, "Validation successful" else: return False, "Data too short" else: return False, "Failed expensive validation" else: if not user_data: return False, "No data provided" else: return False, "Data must be string"
Performance comparison
validator = OptimizedValidator()test_cases = [ "", # Empty string "ab", # Too short 123, # Wrong type "validdata123456", # Valid "invalid!@#", # Invalid characters ] * 100 # Repeat for performance testing
Test optimized version
start_time = time.time() for data in test_cases: validator.validate_optimized(data) optimized_time = time.time() - start_timeprint(f"Optimized version time: {optimized_time:.4f} seconds")
print(f"Cache hits: {validator.cache_hits}, Cache misses: {validator.cache_misses}")
`
Alternatives to Nested If
Dictionary-Based Dispatch
`python
def grade_calculator_nested(score):
"""Traditional nested if approach"""
if score >= 90:
if score >= 97:
return "A+"
elif score >= 93:
return "A"
else:
return "A-"
elif score >= 80:
if score >= 87:
return "B+"
elif score >= 83:
return "B"
else:
return "B-"
elif score >= 70:
return "C"
elif score >= 60:
return "D"
else:
return "F"
def grade_calculator_dispatch(score): """Dictionary dispatch approach""" grade_ranges = [ (97, "A+"), (93, "A"), (90, "A-"), (87, "B+"), (83, "B"), (80, "B-"), (70, "C"), (60, "D"), (0, "F") ] for threshold, grade in grade_ranges: if score >= threshold: return grade return "Invalid"
Match-Case (Python 3.10+)
def process_user_action(action, user_role): """Using match-case instead of nested if""" match action: case "login": match user_role: case "admin": return "Admin dashboard access" case "user": return "User dashboard access" case _: return "Access denied" case "logout": return "Logged out successfully" case "delete" if user_role == "admin": return "Delete operation allowed" case "delete": return "Delete operation denied" case _: return "Unknown action"`State Machine Pattern
`python
class OrderStateMachine:
def __init__(self):
self.state = "pending"
self.transitions = {
"pending": {
"validate": "validated",
"cancel": "cancelled"
},
"validated": {
"process_payment": "payment_processing",
"cancel": "cancelled"
},
"payment_processing": {
"payment_success": "paid",
"payment_failed": "payment_failed"
},
"payment_failed": {
"retry_payment": "payment_processing",
"cancel": "cancelled"
},
"paid": {
"ship": "shipped",
"refund": "refunded"
},
"shipped": {
"deliver": "delivered",
"return": "returned"
},
"delivered": {
"complete": "completed"
}
}
def transition(self, action):
"""Handle state transitions without complex nested if statements"""
if self.state in self.transitions:
if action in self.transitions[self.state]:
old_state = self.state
self.state = self.transitions[self.state][action]
return f"Transitioned from {old_state} to {self.state}"
else:
return f"Invalid action '{action}' for state '{self.state}'"
else:
return f"Invalid state '{self.state}'"
def get_available_actions(self):
"""Get available actions for current state"""
return list(self.transitions.get(self.state, {}).keys())
Usage example
order = OrderStateMachine() actions_sequence = ["validate", "process_payment", "payment_success", "ship", "deliver", "complete"]for action in actions_sequence:
result = order.transition(action)
print(f"Action: {action} -> {result}")
print(f"Available actions: {order.get_available_actions()}")
print()
`
Debugging Nested If Statements
Debugging Techniques
`python
import logging
from functools import wraps
Setup logging
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s') logger = logging.getLogger(__name__)def debug_conditions(func): """Decorator to debug nested condition evaluation""" @wraps(func) def wrapper(args, *kwargs): logger.debug(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}") result = func(args, *kwargs) logger.debug(f"{func.__name__} returned: {result}") return result return wrapper
@debug_conditions def complex_eligibility_check(age, income, credit_score, employment_years): """Complex eligibility check with debugging""" logger.debug(f"Starting eligibility check") if age >= 18: logger.debug("Age requirement (>=18) passed") if age <= 65: logger.debug("Age requirement (<=65) passed") if income >= 25000: logger.debug("Income requirement (>=25000) passed") if credit_score >= 600: logger.debug("Credit score requirement (>=600) passed") if employment_years >= 2: logger.debug("Employment years requirement (>=2) passed") logger.debug("All requirements met - APPROVED") return "APPROVED" else: logger.debug("Employment years requirement failed") return "REJECTED - Insufficient employment history" else: logger.debug("Credit score requirement failed") return "REJECTED - Poor credit score" else: logger.debug("Income requirement failed") return "REJECTED - Insufficient income" else: logger.debug("Age requirement (<=65) failed") return "REJECTED - Age too high" else: logger.debug("Age requirement (>=18) failed") return "REJECTED - Age too low"
Test with debugging
result = complex_eligibility_check(25, 30000, 650, 1) print(f"Final result: {result}")`Testing Nested Conditions
`python
import unittest
from parameterized import parameterized
class TestNestedConditions(unittest.TestCase): def setUp(self): """Set up test fixtures""" self.validator = ComplexValidator() @parameterized.expand([ # (age, income, credit, employment, expected_result, test_description) (25, 30000, 650, 3, "APPROVED", "All requirements met"), (17, 30000, 650, 3, "REJECTED - Age too low", "Age below minimum"), (25, 20000, 650, 3, "REJECTED - Insufficient income", "Income too low"), (25, 30000, 550, 3, "REJECTED - Poor credit score", "Credit score too low"), (25, 30000, 650, 1, "REJECTED - Insufficient employment history", "Employment too short"), (70, 30000, 650, 3, "REJECTED - Age too high", "Age above maximum"), ]) def test_eligibility_conditions(self, age, income, credit, employment, expected, description): """Test various eligibility scenarios""" result = complex_eligibility_check(age, income, credit, employment) self.assertEqual(result, expected, f"Failed: {description}") def test_boundary_conditions(self): """Test boundary values""" boundary_tests = [ (18, 25000, 600, 2, "APPROVED"), # Minimum valid values (65, 25000, 600, 2, "APPROVED"), # Maximum age (18, 24999, 600, 2, "REJECTED - Insufficient income"), # Just below income threshold ] for age, income, credit, employment, expected in boundary_tests: with self.subTest(age=age, income=income, credit=credit, employment=employment): result = complex_eligibility_check(age, income, credit, employment) self.assertEqual(result, expected)
Run tests
if __name__ == '__main__': unittest.main()`Real-World Applications
E-commerce Order Processing
`python
class OrderProcessor:
def __init__(self):
self.inventory = {
"item1": {"stock": 10, "price": 25.99, "category": "electronics"},
"item2": {"stock": 5, "price": 15.50, "category": "books"},
"item3": {"stock": 0, "price": 99.99, "category": "electronics"}
}
self.shipping_rates = {
"standard": {"cost": 5.99, "days": 5},
"express": {"cost": 12.99, "days": 2},
"overnight": {"cost": 24.99, "days": 1}
}
def process_order(self, order_data):
"""Process order with comprehensive validation"""
result = {
"order_id": order_data.get("order_id"),
"status": "pending",
"total_cost": 0,
"shipping_cost": 0,
"estimated_delivery": None,
"errors": [],
"warnings": []
}
# Validate customer information
if "customer" in order_data:
customer = order_data["customer"]
if "email" in customer and "@" in customer["email"]:
if "address" in customer:
address = customer["address"]
if all(field in address for field in ["street", "city", "zip"]):
# Address validation passed
pass
else:
result["errors"].append("Incomplete address information")
return result
else:
result["errors"].append("Shipping address required")
return result
else:
result["errors"].append("Valid email address required")
return result
else:
result["errors"].append("Customer information required")
return result
# Validate and process items
if "items" in order_data and order_data["items"]:
total_cost = 0
for item in order_data["items"]:
if "id" in item and "quantity" in item:
item_id = item["id"]
quantity = item["quantity"]
if item_id in self.inventory:
inventory_item = self.inventory[item_id]
if inventory_item["stock"] >= quantity:
item_cost = inventory_item["price"] * quantity
total_cost += item_cost
# Update inventory
self.inventory[item_id]["stock"] -= quantity
# Check for bulk discount
if quantity >= 5:
discount = item_cost * 0.1 # 10% bulk discount
total_cost -= discount
result["warnings"].append(f"Bulk discount applied for {item_id}")
else:
result["errors"].append(f"Insufficient stock for item {item_id}")
return result
else:
result["errors"].append(f"Item {item_id} not found")
return result
else:
result["errors"].append("Item ID and quantity required")
return result
result["total_cost"] = total_cost
else:
result["errors"].append("Order must contain items")
return result
# Process shipping
if "shipping" in order_data:
shipping_method = order_data["shipping"]
if shipping_method in self.shipping_rates:
shipping_info = self.shipping_rates[shipping_method]
result["shipping_cost"] = shipping_info["cost"]
result["estimated_delivery"] = f"{shipping_info['days']} days"
# Free shipping for orders over $50
if total_cost > 50:
result["shipping_cost"] = 0
result["warnings"].append("Free shipping applied")
else:
result["errors"].append("Invalid shipping method")
return result
else:
# Default to standard shipping
result["shipping_cost"] = self.shipping_rates["standard"]["cost"]
result["estimated_delivery"] = f"{self.shipping_rates['standard']['days']} days"
# Calculate final total
result["total_cost"] += result["shipping_cost"]
# Process payment
if "payment" in order_data:
payment = order_data["payment"]
if "method" in payment and "amount" in payment:
if payment["amount"] >= result["total_cost"]:
if payment["method"] in ["credit_card", "debit_card", "paypal"]:
# Payment processing would happen here
result["status"] = "confirmed"
else:
result["errors"].append("Invalid payment method")
return result
else:
result["errors"].append("Insufficient payment amount")
return result
else:
result["errors"].append("Payment method and amount required")
return result
else:
result["errors"].append("Payment information required")
return result
return result
Example usage
processor = OrderProcessor()sample_order = { "order_id": "ORD-001", "customer": { "email": "customer@example.com", "address": { "street": "123 Main St", "city": "Anytown", "zip": "12345" } }, "items": [ {"id": "item1", "quantity": 2}, {"id": "item2", "quantity": 6} # Bulk quantity for discount ], "shipping": "express", "payment": { "method": "credit_card", "amount": 150.00 } }
result = processor.process_order(sample_order)
print("Order Processing Result:")
for key, value in result.items():
print(f"{key}: {value}")
`
This comprehensive guide covers nested if statements in Python from basic syntax to advanced real-world applications. The examples demonstrate various patterns, best practices, and optimization techniques that developers can apply in their own projects. Understanding these concepts is essential for writing maintainable, efficient, and robust Python code that handles complex decision-making scenarios effectively.