Control Flow Tools: Mastering If, For, While, and Flow Control
TL;DR
Python’s control flow tools include if/elif/else statements, for and while loops, break/continue statements, and the else clause for loops, providing powerful ways to control program execution.
Interesting!
Python is unique among programming languages in that it uses the else clause with loops - for...else
and while...else
execute the else block only if the loop completes normally without hitting a break statement.
If Statements and Conditionals
python code snippet start
# Basic if statement
temperature = 25
if temperature > 30:
print("It's hot!")
elif temperature > 20:
print("It's warm!")
elif temperature > 10:
print("It's cool!")
else:
print("It's cold!")
# Multiple conditions
age = 25
has_license = True
if age >= 18 and has_license:
print("Can drive")
elif age >= 18:
print("Can get a license")
else:
print("Too young to drive")
# Nested if statements
score = 85
grade = ""
if score >= 60:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "C"
else:
grade = "F"
print(f"Score: {score}, Grade: {grade}")
python code snippet end
For Loops - Iteration Over Sequences
python code snippet start
# Basic for loop
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(f"I like {fruit}")
# With enumerate for index access
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# Range-based loops
for i in range(5):
print(f"Number: {i}")
for i in range(1, 6): # 1 to 5
print(f"Number: {i}")
for i in range(0, 10, 2): # Even numbers 0 to 8
print(f"Even: {i}")
# Iterating over strings
word = "Python"
for letter in word:
print(letter)
# Iterating over dictionaries
person = {"name": "Alice", "age": 30, "city": "New York"}
# Keys only
for key in person:
print(key)
# Key-value pairs
for key, value in person.items():
print(f"{key}: {value}")
# Values only
for value in person.values():
print(value)
python code snippet end
While Loops - Condition-Based Iteration
python code snippet start
# Basic while loop
count = 0
while count < 5:
print(f"Count: {count}")
count += 1
# User input loop
while True:
user_input = input("Enter 'quit' to exit: ")
if user_input.lower() == 'quit':
break
print(f"You entered: {user_input}")
# Processing with conditions
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
index = 0
sum_even = 0
while index < len(numbers):
if numbers[index] % 2 == 0:
sum_even += numbers[index]
index += 1
print(f"Sum of even numbers: {sum_even}")
# Fibonacci sequence
a, b = 0, 1
fibonacci = []
while len(fibonacci) < 10:
fibonacci.append(a)
a, b = b, a + b
print(f"First 10 Fibonacci numbers: {fibonacci}")
python code snippet end
Break and Continue Statements
python code snippet start
# break - exit loop immediately
for i in range(10):
if i == 5:
break
print(i) # Prints 0, 1, 2, 3, 4
# continue - skip to next iteration
for i in range(10):
if i % 2 == 0:
continue
print(i) # Prints 1, 3, 5, 7, 9
# break in nested loops
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
break # Only breaks inner loop
print(f"i={i}, j={j}")
# Using flags for breaking nested loops
found = False
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
found = True
break
if found:
break
print(f"Outer loop: i={i}")
# Or use a function to break from nested loops
def find_item():
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
return f"Found at ({i}, {j})"
return "Not found"
result = find_item()
print(result)
python code snippet end
Loop Else Clause
python code snippet start
# for...else - executes if loop completes without break
numbers = [2, 4, 6, 8]
for num in numbers:
if num % 2 != 0:
print("Found odd number")
break
else:
print("All numbers are even") # This will execute
# while...else
count = 0
while count < 3:
print(f"Count: {count}")
count += 1
else:
print("Loop completed normally") # This will execute
# Practical example: searching
def find_prime(n):
"""Find if n is prime using for...else"""
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False # Found a divisor, not prime
else:
return True # Loop completed, no divisors found
print(find_prime(17)) # True
print(find_prime(15)) # False
python code snippet end
Advanced Control Flow Patterns
List Comprehensions with Conditionals
python code snippet start
# Basic list comprehension with condition
numbers = range(10)
evens = [x for x in numbers if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
# Conditional expression in comprehension
labels = ["even" if x % 2 == 0 else "odd" for x in numbers]
print(labels)
# Nested loops in comprehension
matrix = [[i*j for j in range(3)] for i in range(3)]
print(matrix) # [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
# Flattening with multiple for clauses
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Complex filtering
words = ["apple", "banana", "cherry", "date"]
long_words = [word.upper() for word in words if len(word) > 5]
print(long_words) # ['BANANA', 'CHERRY']
python code snippet end
Exception Handling in Loops
python code snippet start
# Handle exceptions in loops
numbers = ["1", "2", "abc", "4", "xyz"]
converted = []
for num_str in numbers:
try:
converted.append(int(num_str))
except ValueError:
print(f"Skipping invalid number: {num_str}")
continue
print(f"Converted numbers: {converted}")
# Using finally in loops
def process_files(filenames):
for filename in filenames:
file = None
try:
file = open(filename, 'r')
content = file.read()
print(f"Processed {filename}: {len(content)} characters")
except FileNotFoundError:
print(f"File not found: {filename}")
finally:
if file:
file.close()
# process_files(['file1.txt', 'nonexistent.txt', 'file2.txt'])
python code snippet end
Generator Expressions vs Loops
python code snippet start
# Traditional loop approach
def square_evens_loop(numbers):
result = []
for num in numbers:
if num % 2 == 0:
result.append(num ** 2)
return result
# Generator expression approach
def square_evens_gen(numbers):
return (num ** 2 for num in numbers if num % 2 == 0)
# Usage comparison
numbers = range(10)
loop_result = square_evens_loop(numbers)
gen_result = list(square_evens_gen(numbers))
print(f"Loop result: {loop_result}")
print(f"Generator result: {gen_result}")
python code snippet end
Practical Examples
Data Processing Pipeline
python code snippet start
def process_sales_data(sales_records):
"""Process sales data with control flow"""
processed_sales = []
total_revenue = 0
invalid_records = 0
for record in sales_records:
# Validate record
if not isinstance(record, dict):
invalid_records += 1
continue
if 'amount' not in record or 'date' not in record:
invalid_records += 1
continue
try:
amount = float(record['amount'])
except (ValueError, TypeError):
invalid_records += 1
continue
# Process valid record
if amount > 0:
processed_record = {
'amount': amount,
'date': record['date'],
'category': record.get('category', 'unknown')
}
# Apply business rules
if amount > 1000:
processed_record['priority'] = 'high'
elif amount > 100:
processed_record['priority'] = 'medium'
else:
processed_record['priority'] = 'low'
processed_sales.append(processed_record)
total_revenue += amount
else:
invalid_records += 1
return {
'processed_sales': processed_sales,
'total_revenue': total_revenue,
'invalid_records': invalid_records,
'success_rate': len(processed_sales) / len(sales_records) * 100
}
# Sample data
sales_data = [
{'amount': '150.50', 'date': '2024-01-01', 'category': 'electronics'},
{'amount': '2500.00', 'date': '2024-01-02'},
{'amount': 'invalid', 'date': '2024-01-03'},
{'amount': '75.25', 'date': '2024-01-04', 'category': 'books'},
]
result = process_sales_data(sales_data)
print(f"Processed {len(result['processed_sales'])} records")
print(f"Total revenue: ${result['total_revenue']:.2f}")
print(f"Success rate: {result['success_rate']:.1f}%")
python code snippet end
Menu System with User Input
python code snippet start
def calculator_menu():
"""Interactive calculator with menu system"""
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
if y == 0:
raise ValueError("Cannot divide by zero")
return x / y
operations = {
'1': ('Addition', add),
'2': ('Subtraction', subtract),
'3': ('Multiplication', multiply),
'4': ('Division', divide)
}
while True:
# Display menu
print("\n=== Calculator ===")
for key, (name, _) in operations.items():
print(f"{key}. {name}")
print("5. Quit")
choice = input("\nSelect operation (1-5): ").strip()
if choice == '5':
print("Goodbye!")
break
if choice not in operations:
print("Invalid choice. Please try again.")
continue
# Get numbers
try:
num1 = float(input("Enter first number: "))
num2 = float(input("Enter second number: "))
except ValueError:
print("Invalid input. Please enter valid numbers.")
continue
# Perform calculation
try:
operation_name, operation_func = operations[choice]
result = operation_func(num1, num2)
print(f"\n{operation_name}: {num1} and {num2} = {result}")
except ValueError as e:
print(f"Error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
# calculator_menu() # Uncomment to run interactive menu
python code snippet end
File Processing with Control Flow
python code snippet start
import os
def analyze_text_files(directory):
"""Analyze all text files in a directory"""
if not os.path.exists(directory):
print(f"Directory {directory} does not exist")
return
analysis = {
'files_processed': 0,
'total_lines': 0,
'total_words': 0,
'total_chars': 0,
'errors': []
}
# Process each file in directory
for filename in os.listdir(directory):
if not filename.endswith('.txt'):
continue
filepath = os.path.join(directory, filename)
try:
with open(filepath, 'r', encoding='utf-8') as file:
line_count = 0
word_count = 0
char_count = 0
for line in file:
line_count += 1
char_count += len(line)
# Count words (split on whitespace)
words = line.strip().split()
word_count += len(words)
# Update totals
analysis['files_processed'] += 1
analysis['total_lines'] += line_count
analysis['total_words'] += word_count
analysis['total_chars'] += char_count
print(f"Processed {filename}: {line_count} lines, {word_count} words")
except UnicodeDecodeError:
error_msg = f"Encoding error in {filename}"
analysis['errors'].append(error_msg)
print(error_msg)
except PermissionError:
error_msg = f"Permission denied for {filename}"
analysis['errors'].append(error_msg)
print(error_msg)
except Exception as e:
error_msg = f"Error processing {filename}: {str(e)}"
analysis['errors'].append(error_msg)
print(error_msg)
# Print summary
if analysis['files_processed'] > 0:
avg_lines = analysis['total_lines'] / analysis['files_processed']
avg_words = analysis['total_words'] / analysis['files_processed']
print(f"\n=== Analysis Summary ===")
print(f"Files processed: {analysis['files_processed']}")
print(f"Total lines: {analysis['total_lines']}")
print(f"Total words: {analysis['total_words']}")
print(f"Total characters: {analysis['total_chars']}")
print(f"Average lines per file: {avg_lines:.1f}")
print(f"Average words per file: {avg_words:.1f}")
if analysis['errors']:
print(f"\nErrors encountered: {len(analysis['errors'])}")
for error in analysis['errors']:
print(f" - {error}")
else:
print("No text files found to process")
return analysis
# Example usage
# result = analyze_text_files('.')
python code snippet end
Performance Tips and Best Practices
python code snippet start
# Use enumerate instead of range(len())
# Bad
items = ['a', 'b', 'c', 'd']
for i in range(len(items)):
print(f"{i}: {items[i]}")
# Good
for i, item in enumerate(items):
print(f"{i}: {item}")
# Use zip for parallel iteration
# Bad
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for i in range(len(names)):
print(f"{names[i]} is {ages[i]} years old")
# Good
for name, age in zip(names, ages):
print(f"{name} is {age} years old")
# Use any() and all() for boolean checks
# Bad
has_negative = False
for num in numbers:
if num < 0:
has_negative = True
break
# Good
has_negative = any(num < 0 for num in numbers)
# Bad
all_positive = True
for num in numbers:
if num <= 0:
all_positive = False
break
# Good
all_positive = all(num > 0 for num in numbers)
# Use break and continue to avoid deep nesting
# Bad
for item in items:
if item.is_valid():
if item.needs_processing():
if item.has_permission():
process_item(item)
# Good
for item in items:
if not item.is_valid():
continue
if not item.needs_processing():
continue
if not item.has_permission():
continue
process_item(item)
python code snippet end
Common Pitfalls and Solutions
python code snippet start
# Pitfall 1: Modifying list while iterating
# Bad - can cause unexpected behavior
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # Don't do this!
# Good - iterate over a copy or use list comprehension
numbers = [1, 2, 3, 4, 5]
for num in numbers[:]: # Iterate over copy
if num % 2 == 0:
numbers.remove(num)
# Or better - use list comprehension
numbers = [num for num in numbers if num % 2 != 0]
# Pitfall 2: Variable scope in loops
# Variables defined in loops persist after the loop
for i in range(5):
x = i * 2
print(x) # x is still accessible and equals 8
# Pitfall 3: Late binding in loops with lambdas
# Bad
functions = []
for i in range(5):
functions.append(lambda: i) # All will return 4!
# Good
functions = []
for i in range(5):
functions.append(lambda x=i: x) # Capture current value
# Pitfall 4: Infinite loops
# Always ensure loop variables are modified
count = 0
while count < 10:
print(count)
# count += 1 # Don't forget this!
python code snippet end
Control flow tools are fundamental to programming logic, enabling you to create sophisticated programs that respond to different conditions and process data efficiently.
These control flow patterns work exceptionally well with the walrus operator for more expressive code and form the foundation for understanding data structure operations . The patterns shown here integrate with built-in functions and implement Zen of Python principles for readable code. Modern control flow includes pattern matching for sophisticated branching and builds on context management for resource handling.
Reference: Python Tutorial - More Control Flow Tools