Course Topics
Introduction Python Overview Setting Up Python Python Syntax Basics First Steps with Python Comparing Python with Other Languages Basics Variables and Data Types Input and Output Type Conversion Comments and Code Readability Naming Conventions Control Flow Conditional Statements Loops in Python Loop Control Mechanisms Nested Control Structures Data Structures Working with Strings Lists Tuples Sets Dictionaries Comprehensions Iterators and Generators Functions Defining and Calling Functions Function Arguments and Parameters Lambda Functions Return Values Recursion Variable Scope in Functions Modules and Packages Importing Modules Built-in Modules Creating Custom Modules Working with Packages Virtual Environments Managing Packages with pip Object-Oriented Programming Classes and Objects Attributes and Methods Constructors and Initializers Inheritance and Polymorphism Encapsulation and Abstraction Class Methods and Static Methods Using super() and Method Resolution File Handling Reading and Writing Text Files File Modes and File Pointers Using Context Managers (with) Working with CSV Files Handling JSON Data Error Handling Types of Errors and Exceptions Try, Except, Finally Blocks Raising Exceptions Built-in vs Custom Exceptions Exception Handling Best Practices Advanced Python Decorators Advanced Generators Context Managers Functional Programming Tools Coroutines and Async Programming Introduction to Metaclasses Memory Management in Python Useful Libraries Math Module Random Module Date and Time Handling Regular Expressions (re) File and OS Operations (os, sys, shutil) Data Structures Enhancements (collections, itertools) Web APIs (requests) Data Analysis Libraries (NumPy, Pandas) Visualization Tools (matplotlib) Database Access SQLite in Python Connecting to MySQL/PostgreSQL Executing SQL Queries Using ORMs (SQLAlchemy Intro) Transactions and Error Handling Web Development Introduction to Web Frameworks Flask Basics (Routing, Templates) Django Overview Handling Forms and Requests Creating REST APIs Working with JSON and HTTP Methods Testing and Debugging Debugging Techniques Using assert and Logging Writing Unit Tests (unittest) Introduction to pytest Handling and Fixing Common Bugs Automation and Scripting Automating File Operations Web Scraping with BeautifulSoup Automating Excel Tasks (openpyxl) Sending Emails with Python Task Scheduling and Timers System Automation with subprocess

Loops in Python

What are Loops?

Loops are programming constructs that allow you to repeat a block of code multiple times. Instead of writing the same code over and over, loops let you execute code repeatedly while a condition is true or for a specific number of iterations.

Python provides two main types of loops: for loops and while loops. Each serves different purposes and is useful in different situations.

example:

# Without a loop - repetitive and inefficient
print("Welcome to Python!")
print("Welcome to Python!")
print("Welcome to Python!")
print("Welcome to Python!")
print("Welcome to Python!")

# With a loop - clean and efficient
for i in range(5):
    print("Welcome to Python!")

The for Loop

The for loop is used to iterate over a sequence (like a list, string, or range) or any iterable object. It's perfect when you know how many times you want to repeat something or when you want to process each item in a collection.

Basic for Loop with range()

# Print numbers from 0 to 4
for i in range(5):
    print(f"Number: {i}")

# Print numbers from 1 to 10
for i in range(1, 11):
    print(f"Count: {i}")

# Print even numbers from 2 to 20
for i in range(2, 21, 2):
    print(f"Even number: {i}")

# Countdown from 10 to 1
for i in range(10, 0, -1):
    print(f"Countdown: {i}")

Looping Through Lists

# Iterate through a list of names
students = ["Alice", "Bob", "Charlie", "Diana", "Emma"]

for student in students:
    print(f"Hello, {student}!")

# Process a list of numbers
scores = [85, 92, 78, 96, 88]

for score in scores:
    if score >= 90:
        print(f"Excellent score: {score}")
    elif score >= 80:
        print(f"Good score: {score}")
    else:
        print(f"Score needs improvement: {score}")

# Calculate total and average
total = 0
for score in scores:
    total += score

average = total / len(scores)
print(f"Total: {total}, Average: {average:.1f}")

Looping Through Strings

# Iterate through each character in a string
name = "Python"

for letter in name:
    print(f"Letter: {letter}")

# Count vowels in a string
message = "Hello World"
vowels = "aeiouAEIOU"
vowel_count = 0

for char in message:
    if char in vowels:
        vowel_count += 1

print(f"Number of vowels in '{message}': {vowel_count}")

# Create a reversed string
original = "Programming"
reversed_string = ""

for char in original:
    reversed_string = char + reversed_string

print(f"Original: {original}")
print(f"Reversed: {reversed_string}")

Using enumerate() for Index and Value

# Get both index and value while looping
fruits = ["apple", "banana", "cherry", "date"]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# Start enumeration from 1 instead of 0
for position, fruit in enumerate(fruits, 1):
    print(f"Position {position}: {fruit}")

# Process items with their positions
shopping_list = ["milk", "bread", "eggs", "cheese"]

print("Shopping List:")
for item_number, item in enumerate(shopping_list, 1):
    print(f"{item_number}. {item}")

The while Loop

The while loop continues executing as long as a condition remains true. It's useful when you don't know exactly how many iterations you need or when the loop should continue based on changing conditions.

Basic while Loop

# Count from 1 to 5
count = 1
while count <= 5:
    print(f"Count: {count}")
    count += 1

# User input validation
password = ""
while password != "secret123":
    password = input("Enter password: ")
    if password != "secret123":
        print("Incorrect password. Try again.")

print("Access granted!")

# Generate random numbers until we get 5
import random

number = 0
attempts = 0

while number != 5:
    number = random.randint(1, 10)
    attempts += 1
    print(f"Attempt {attempts}: Got {number}")

print(f"Found 5 after {attempts} attempts!")

while Loop with Conditions

# Bank account simulation
balance = 1000

while balance > 0:
    print(f"Current balance: ${balance}")
    withdrawal = float(input("Enter withdrawal amount (0 to quit): "))

    if withdrawal == 0:
        break
    elif withdrawal > balance:
        print("Insufficient funds!")
    else:
        balance -= withdrawal
        print(f"Withdrew ${withdrawal}")

print(f"Final balance: ${balance}")

# Number guessing game
import random

secret_number = random.randint(1, 100)
guess = 0
attempts = 0
max_attempts = 7

while guess != secret_number and attempts < max_attempts:
    guess = int(input(f"Guess the number (1-100). Attempt {attempts + 1}/{max_attempts}: "))
    attempts += 1

    if guess < secret_number:
        print("Too low!")
    elif guess > secret_number:
        print("Too high!")
    else:
        print(f"Congratulations! You guessed it in {attempts} attempts!")

if guess != secret_number:
    print(f"Game over! The number was {secret_number}")

Nested Loops

You can place loops inside other loops to handle more complex repetitive tasks.

Basic Nested Loops

# Multiplication table
print("Multiplication Table:")
for i in range(1, 6):
    for j in range(1, 6):
        result = i * j
        print(f"{i} x {j} = {result:2d}", end="  ")
    print()  # New line after each row

# Pattern printing
print("\nStar Pattern:")
for row in range(1, 6):
    for col in range(row):
        print("*", end=" ")
    print()  # New line after each row

# Number pyramid
print("\nNumber Pyramid:")
for row in range(1, 6):
    for col in range(1, row + 1):
        print(col, end=" ")
    print()

Processing 2D Data

# Student grades matrix
grades = [
    [85, 92, 78],  # Alice's grades
    [90, 88, 95],  # Bob's grades
    [79, 83, 91]   # Charlie's grades
]

student_names = ["Alice", "Bob", "Charlie"]
subjects = ["Math", "Science", "English"]

# Calculate average for each student
for i, student in enumerate(student_names):
    total = 0
    for grade in grades[i]:
        total += grade
    average = total / len(grades[i])
    print(f"{student}'s average: {average:.1f}")

# Calculate average for each subject
print("\nSubject Averages:")
for j, subject in enumerate(subjects):
    total = 0
    for i in range(len(grades)):
        total += grades[i][j]
    average = total / len(grades)
    print(f"{subject} average: {average:.1f}")

Loop Control Statements

Python provides statements to control loop execution: break, continue, and pass.

The break Statement

# Exit loop early
numbers = [1, 3, 7, 2, 9, 4, 6]

for num in numbers:
    if num == 9:
        print("Found 9! Stopping search.")
        break
    print(f"Checking: {num}")

# Menu system with exit option
while True:
    print("\n=== Main Menu ===")
    print("1. View Profile")
    print("2. Edit Settings")
    print("3. Logout")

    choice = input("Enter choice (1-3): ")

    if choice == "1":
        print("Displaying profile...")
    elif choice == "2":
        print("Opening settings...")
    elif choice == "3":
        print("Logging out...")
        break
    else:
        print("Invalid choice!")

# Find first even number
numbers = [1, 3, 5, 8, 11, 12, 15]

for num in numbers:
    if num % 2 == 0:
        print(f"First even number found: {num}")
        break
else:
    print("No even number found")

The continue Statement

# Skip specific iterations
for i in range(1, 11):
    if i % 2 == 0:
        continue  # Skip even numbers
    print(f"Odd number: {i}")

# Process only valid data
data = [10, -5, 8, 0, 15, -2, 20]

positive_sum = 0
for number in data:
    if number <= 0:
        continue  # Skip non-positive numbers
    positive_sum += number
    print(f"Added {number}, sum now: {positive_sum}")

print(f"Sum of positive numbers: {positive_sum}")

# Skip empty or invalid inputs
users = ["Alice", "", "Bob", "   ", "Charlie", None]

print("Valid users:")
for user in users:
    if not user or not user.strip():
        continue  # Skip empty or whitespace-only names
    print(f"- {user}")

The pass Statement

# Placeholder for future implementation
for i in range(5):
    if i == 2:
        pass  # TODO: Add special handling for i=2
    else:
        print(f"Processing: {i}")

# Empty loop body (rare but sometimes needed)
for item in some_list:
    pass  # Just iterate without doing anything

# Placeholder in conditional structures within loops
for user in users:
    if user.is_admin():
        pass  # Admin handling to be implemented
    elif user.is_moderator():
        print(f"Moderator: {user.name}")
    else:
        print(f"Regular user: {user.name}")

Loop Patterns and Techniques

Accumulator Pattern

# Sum of numbers
numbers = [10, 20, 30, 40, 50]
total = 0

for number in numbers:
    total += number

print(f"Total: {total}")

# Product of numbers
numbers = [2, 3, 4, 5]
product = 1

for number in numbers:
    product *= number

print(f"Product: {product}")

# Concatenating strings
words = ["Python", "is", "awesome"]
sentence = ""

for word in words:
    sentence += word + " "

print(f"Sentence: {sentence.strip()}")

# Finding maximum
scores = [85, 92, 78, 96, 88]
max_score = scores[0]

for score in scores:
    if score > max_score:
        max_score = score

print(f"Highest score: {max_score}")

Counter Pattern

# Count specific items
grades = ['A', 'B', 'A', 'C', 'B', 'A', 'D']
a_count = 0

for grade in grades:
    if grade == 'A':
        a_count += 1

print(f"Number of A grades: {a_count}")

# Count multiple categories
text = "Hello World"
vowel_count = 0
consonant_count = 0

for char in text.lower():
    if char.isalpha():
        if char in 'aeiou':
            vowel_count += 1
        else:
            consonant_count += 1

print(f"Vowels: {vowel_count}, Consonants: {consonant_count}")

# Count words by length
sentence = "Python programming is fun and educational"
words = sentence.split()
short_words = 0  # 1-4 letters
medium_words = 0  # 5-7 letters
long_words = 0   # 8+ letters

for word in words:
    if len(word) <= 4:
        short_words += 1
    elif len(word) <= 7:
        medium_words += 1
    else:
        long_words += 1

print(f"Short: {short_words}, Medium: {medium_words}, Long: {long_words}")

Filter Pattern

# Filter positive numbers
numbers = [10, -5, 8, -2, 15, -1, 20]
positive_numbers = []

for number in numbers:
    if number > 0:
        positive_numbers.append(number)

print(f"Positive numbers: {positive_numbers}")

# Filter students by grade
students = [
    {"name": "Alice", "grade": 92},
    {"name": "Bob", "grade": 76},
    {"name": "Charlie", "grade": 88},
    {"name": "Diana", "grade": 95}
]

honor_students = []
for student in students:
    if student["grade"] >= 90:
        honor_students.append(student["name"])

print(f"Honor students: {honor_students}")

# Filter valid email addresses
emails = ["user@example.com", "invalid-email", "test@test.com", "bad@", "good@domain.org"]
valid_emails = []

for email in emails:
    if "@" in email and "." in email:
        valid_emails.append(email)

print(f"Valid emails: {valid_emails}")

Working with Dictionaries in Loops

# Iterate through dictionary keys
student_grades = {"Alice": 92, "Bob": 85, "Charlie": 90, "Diana": 88}

print("Student names:")
for name in student_grades:
    print(f"- {name}")

# Iterate through values
print("\nGrades:")
for grade in student_grades.values():
    print(f"- {grade}")

# Iterate through key-value pairs
print("\nStudent grades:")
for name, grade in student_grades.items():
    print(f"{name}: {grade}")

# Update dictionary values
for name in student_grades:
    if student_grades[name] >= 90:
        student_grades[name] = "A"
    elif student_grades[name] >= 80:
        student_grades[name] = "B"
    else:
        student_grades[name] = "C"

print("\nLetter grades:")
for name, letter_grade in student_grades.items():
    print(f"{name}: {letter_grade}")

Practical Examples

Example 1: Password Strength Checker

def check_password_strength():
    """Check password strength with detailed feedback."""

    while True:
        password = input("Enter a password to check (or 'quit' to exit): ")

        if password.lower() == 'quit':
            break

        # Initialize criteria checks
        has_upper = False
        has_lower = False
        has_digit = False
        has_special = False
        special_chars = "!@#$%^&*()_+-=[]{}|;:,.<>?"

        # Check each character
        for char in password:
            if char.isupper():
                has_upper = True
            elif char.islower():
                has_lower = True
            elif char.isdigit():
                has_digit = True
            elif char in special_chars:
                has_special = True

        # Calculate strength score
        score = 0
        feedback = []

        if len(password) >= 8:
            score += 1
        else:
            feedback.append("Add more characters (minimum 8)")

        if has_upper:
            score += 1
        else:
            feedback.append("Add uppercase letters")

        if has_lower:
            score += 1
        else:
            feedback.append("Add lowercase letters")

        if has_digit:
            score += 1
        else:
            feedback.append("Add numbers")

        if has_special:
            score += 1
        else:
            feedback.append("Add special characters")

        # Determine strength level
        if score == 5:
            strength = "Very Strong"
        elif score >= 4:
            strength = "Strong"
        elif score >= 3:
            strength = "Moderate"
        elif score >= 2:
            strength = "Weak"
        else:
            strength = "Very Weak"

        print(f"\nPassword strength: {strength} ({score}/5)")
        if feedback:
            print("Suggestions:")
            for suggestion in feedback:
                print(f"- {suggestion}")
        print("-" * 40)

check_password_strength()

Example 2: Sales Report Generator

def generate_sales_report():
    """Generate a comprehensive sales report."""

    # Sample sales data
    sales_data = [
        {"product": "Laptop", "quantity": 5, "price": 1200, "month": "January"},
        {"product": "Mouse", "quantity": 20, "price": 25, "month": "January"},
        {"product": "Keyboard", "quantity": 15, "price": 75, "month": "January"},
        {"product": "Laptop", "quantity": 8, "price": 1200, "month": "February"},
        {"product": "Mouse", "quantity": 25, "price": 25, "month": "February"},
        {"product": "Monitor", "quantity": 10, "price": 300, "month": "February"},
    ]

    print("=== SALES REPORT ===\n")

    # Calculate total revenue by product
    product_revenue = {}
    for sale in sales_data:
        product = sale["product"]
        revenue = sale["quantity"] * sale["price"]

        if product in product_revenue:
            product_revenue[product] += revenue
        else:
            product_revenue[product] = revenue

    print("Revenue by Product:")
    total_revenue = 0
    for product, revenue in product_revenue.items():
        print(f"{product}: ${revenue:,}")
        total_revenue += revenue

    print(f"\nTotal Revenue: ${total_revenue:,}")

    # Calculate monthly totals
    monthly_revenue = {}
    for sale in sales_data:
        month = sale["month"]
        revenue = sale["quantity"] * sale["price"]

        if month in monthly_revenue:
            monthly_revenue[month] += revenue
        else:
            monthly_revenue[month] = revenue

    print("\nRevenue by Month:")
    for month, revenue in monthly_revenue.items():
        print(f"{month}: ${revenue:,}")

    # Find best-selling product by quantity
    product_quantities = {}
    for sale in sales_data:
        product = sale["product"]
        quantity = sale["quantity"]

        if product in product_quantities:
            product_quantities[product] += quantity
        else:
            product_quantities[product] = quantity

    best_seller = ""
    max_quantity = 0
    for product, quantity in product_quantities.items():
        if quantity > max_quantity:
            max_quantity = quantity
            best_seller = product

    print(f"\nBest Selling Product: {best_seller} ({max_quantity} units)")

    # Calculate average sale value
    total_sales_count = len(sales_data)
    average_sale = total_revenue / total_sales_count
    print(f"Average Sale Value: ${average_sale:.2f}")

generate_sales_report()

Example 3: Text Analysis Tool

def analyze_text():
    """Comprehensive text analysis tool."""

    text = input("Enter text to analyze: ")

    if not text.strip():
        print("No text provided!")
        return

    print(f"\n=== ANALYSIS OF: '{text}' ===\n")

    # Basic statistics
    char_count = len(text)
    char_count_no_spaces = len(text.replace(" ", ""))
    word_count = len(text.split())
    sentence_count = text.count('.') + text.count('!') + text.count('?')

    print("Basic Statistics:")
    print(f"Characters (with spaces): {char_count}")
    print(f"Characters (without spaces): {char_count_no_spaces}")
    print(f"Words: {word_count}")
    print(f"Sentences: {sentence_count}")

    # Character frequency analysis
    char_frequency = {}
    for char in text.lower():
        if char.isalpha():
            if char in char_frequency:
                char_frequency[char] += 1
            else:
                char_frequency[char] = 1

    print(f"\nCharacter Frequencies:")
    for char in sorted(char_frequency.keys()):
        print(f"'{char}': {char_frequency[char]}")

    # Word frequency analysis
    words = text.lower().split()
    word_frequency = {}

    for word in words:
        # Remove punctuation
        clean_word = ""
        for char in word:
            if char.isalpha():
                clean_word += char

        if clean_word:
            if clean_word in word_frequency:
                word_frequency[clean_word] += 1
            else:
                word_frequency[clean_word] = 1

    print(f"\nWord Frequencies:")
    for word in sorted(word_frequency.keys()):
        print(f"'{word}': {word_frequency[word]}")

    # Find longest and shortest words
    longest_word = ""
    shortest_word = None

    for word in word_frequency.keys():
        if len(word) > len(longest_word):
            longest_word = word
        if shortest_word is None or len(word) < len(shortest_word):
            shortest_word = word

    print(f"\nLongest word: '{longest_word}' ({len(longest_word)} letters)")
    print(f"Shortest word: '{shortest_word}' ({len(shortest_word)} letters)")

    # Vowel and consonant analysis
    vowels = "aeiou"
    vowel_count = 0
    consonant_count = 0

    for char in text.lower():
        if char.isalpha():
            if char in vowels:
                vowel_count += 1
            else:
                consonant_count += 1

    print(f"\nVowels: {vowel_count}")
    print(f"Consonants: {consonant_count}")

    if vowel_count + consonant_count > 0:
        vowel_percentage = (vowel_count / (vowel_count + consonant_count)) * 100
        print(f"Vowel percentage: {vowel_percentage:.1f}%")

analyze_text()

Loop Optimization Tips

Efficient Loop Writing

# Avoid recalculating inside loops
# Inefficient
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for number in numbers:
    if number % 2 == 0:
        print(f"{number} is even")

# More efficient for complex calculations
def is_even(n):
    return n % 2 == 0

for number in numbers:
    if is_even(number):
        print(f"{number} is even")

# Use list comprehensions for simple transformations
# Traditional loop
squares = []
for i in range(10):
    squares.append(i ** 2)

# List comprehension (more Pythonic)
squares = [i ** 2 for i in range(10)]

# Use built-in functions when possible
numbers = [1, 2, 3, 4, 5]

# Instead of manual sum
total = 0
for number in numbers:
    total += number

# Use built-in sum()
total = sum(numbers)

Summary

Loops are fundamental for repetitive tasks in programming:

Key Concepts:
- for loops iterate over sequences and collections
- while loops continue based on conditions
- range() generates number sequences
- enumerate() provides index and value pairs
- break exits loops early
- continue skips to next iteration
- pass serves as a placeholder

Common Patterns:
- Accumulator pattern for sums and products
- Counter pattern for counting occurrences
- Filter pattern for selecting items
- Nested loops for 2D data processing

Best Practices:
- Choose the right loop type for your task
- Use descriptive variable names
- Avoid infinite loops with proper exit conditions
- Consider list comprehensions for simple transformations
- Use built-in functions when appropriate

Mastering loops will enable you to process data efficiently, automate repetitive tasks, and build more sophisticated programs!