Python Loops - Complete Guide

Understanding Loops in Python

Loops in Python allow you to execute a block of code repeatedly. They are essential for automating repetitive tasks, processing collections of data, and creating iterative algorithms.

Python supports two primary types of loops:

  • for loops: Used for iterating over a sequence (list, tuple, string, etc.)
  • while loops: Used for executing code as long as a condition is true
# Basic for loop example
for i in range(5):
    print(i)  # Prints 0, 1, 2, 3, 4

# Basic while loop example
count = 0
while count < 5:
    print(count)  # Prints 0, 1, 2, 3, 4
    count += 1

For Loops

The for loop in Python is designed to iterate over a sequence (like a list, tuple, dictionary, set, or string). This makes it perfect for processing collections of data.

Basic For Loop Syntax

# Iterating over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# Iterating over a string
for char in "Python":
    print(char)

# Iterating with range()
for i in range(5):  # 0 to 4
    print(i)

# Range with start and stop
for i in range(2, 6):  # 2 to 5
    print(i)

# Range with start, stop, and step
for i in range(1, 10, 2):  # 1, 3, 5, 7, 9
    print(i)

Iterating Over Collections

# Iterating over a dictionary
person = {"name": "Alice", "age": 30, "city": "New York"}

# Iterating over keys (default)
for key in person:
    print(key, person[key])

# Iterating over key-value pairs
for key, value in person.items():
    print(f"{key}: {value}")

# Iterating over values only
for value in person.values():
    print(value)

# Iterating with index using enumerate()
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")  # 0: apple, 1: banana, 2: cherry

# Iterating over multiple lists with zip()
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")

While Loops

The while loop executes a block of code as long as a specified condition is true. It's useful when you don't know in advance how many times a loop needs to run.

Basic While Loop Syntax

# Simple countdown
count = 5
while count > 0:
    print(count)
    count -= 1
print("Blast off!")

# Loop with user input
user_input = ""
while user_input.lower() != "quit":
    user_input = input("Enter a command (type 'quit' to exit): ")
    print(f"You entered: {user_input}")

# Infinite loop with break
while True:
    user_input = input("Enter 'quit' to exit: ")
    if user_input.lower() == "quit":
        break
    print(f"You entered: {user_input}")

Use Cases for While Loops

  • When the number of iterations is unknown
  • When you need to continue until a specific condition is met
  • For implementing retry logic or polling
  • Game loops that run until the player quits

Loop Control Statements

Python provides several statements to control the flow of loops:

  • break: Exits the loop completely
  • continue: Skips the current iteration and moves to the next one
  • else: Executes when the loop completes normally (not after a break)

Break Statement

# Break when a condition is met
for i in range(1, 11):
    if i == 5:
        print("Found 5! Breaking the loop.")
        break
    print(i)
# Output: 1, 2, 3, 4, Found 5! Breaking the loop.

# Break in a while loop
number = 0
while True:
    number += 1
    if number > 10:
        break
    print(number)

Continue Statement

# Skip even numbers
for i in range(1, 11):
    if i % 2 == 0:
        continue  # Skip the rest of the code and go to next iteration
    print(i)
# Output: 1, 3, 5, 7, 9

# Skip specific values
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
for fruit in fruits:
    if fruit == "cherry":
        continue
    print(fruit)

Else Clause in Loops

# Else clause executes after loop completes
for i in range(5):
    print(i)
else:
    print("Loop completed successfully!")

# Else won't execute if loop is broken
for i in range(5):
    print(i)
    if i == 3:
        break
else:
    print("This won't print because the loop was broken")

Nested Loops

Loops can be nested inside one another. This is useful for working with multi-dimensional data or when you need to perform complex iterations.

# Simple nested loop
for i in range(3):
    for j in range(3):
        print(f"({i}, {j})", end=" ")
    print()  # New line after inner loop

# Multiplication table
for i in range(1, 6):
    for j in range(1, 6):
        print(f"{i * j:2d}", end=" ")
    print()

# Nested loop with 2D list
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

for row in matrix:
    for element in row:
        print(element, end=" ")
    print()

Performance Considerations

Nested loops can be computationally expensive. The time complexity is typically O(n²) for doubly nested loops, where n is the number of iterations in each loop.

List Comprehensions

List comprehensions provide a concise way to create lists based on existing lists or other iterable objects. They're a powerful Python feature that can replace certain types of for loops.

Basic List Comprehension

# Creating a list of squares
# Regular for loop approach
squares = []
for x in range(10):
    squares.append(x**2)
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Using list comprehension
squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Filtering with list comprehension
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

Advanced List Comprehensions

# Nested list comprehension
matrix = [[j for j in range(3)] for i in range(3)]
print(matrix)  # [[0, 1, 2], [0, 1, 2], [0, 1, 2]]

# Multiple conditions
values = [x for x in range(100) if x % 2 == 0 if x % 5 == 0]
print(values)  # [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

# If-else in list comprehension
numbers = [-4, -2, 0, 2, 4]
absolute = [x if x >= 0 else -x for x in numbers]
print(absolute)  # [4, 2, 0, 2, 4]

Other Comprehensions

# Dictionary comprehension
squares_dict = {x: x**2 for x in range(6)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Set comprehension
unique_lengths = {len(word) for word in ["hello", "world", "python", "code"]}
print(unique_lengths)  # {5, 4, 6}

# Generator expression (parentheses instead of brackets)
numbers_gen = (x**2 for x in range(5))
print(numbers_gen)  #  at 0x...>
print(list(numbers_gen))  # [0, 1, 4, 9, 16]

Loop Optimization Techniques

Loops can sometimes be performance bottlenecks. Here are techniques to optimize loops in Python.

Performance Tips

# 1. Avoid expensive operations in loops
# Poor performance
import time
start = time.time()
for i in range(1000000):
    i / 2  # Performs division 1,000,000 times
print(f"Time: {time.time() - start:.4f} seconds")

# 2. Use list comprehensions for simple loops
# list comprehension is generally faster than for loop for creating lists
start = time.time()
squares = [x**2 for x in range(1000000)]
print(f"Comprehension time: {time.time() - start:.4f} seconds")

start = time.time()
squares = []
for x in range(1000000):
    squares.append(x**2)
print(f"For loop time: {time.time() - start:.4f} seconds")

# 3. Move constant operations outside the loop
import math
# Inefficient
for i in range(1000):
    result = i * math.pi  # math.pi calculated in each iteration

# More efficient
pi_value = math.pi
for i in range(1000):
    result = i * pi_value  # Constant value calculated once

Using Specialized Tools

# Using NumPy for faster array operations
import numpy as np

# NumPy vectorization vs. loop
arr = np.array(range(1000000))

# Using loop (slower)
start = time.time()
result = []
for i in arr:
    result.append(i**2)
print(f"Loop time: {time.time() - start:.4f} seconds")

# Using NumPy vectorization (faster)
start = time.time()
result = arr**2
print(f"NumPy time: {time.time() - start:.4f} seconds")

Common Loop Patterns

Searching and Filtering

# Finding an element
numbers = [4, 7, 2, 9, 1, 5]
target = 9
found = False

for num in numbers:
    if num == target:
        found = True
        break

print(f"Found: {found}")

# Filtering elements
numbers = [4, 7, 2, 9, 1, 5]
even_numbers = []

for num in numbers:
    if num % 2 == 0:
        even_numbers.append(num)

print(f"Even numbers: {even_numbers}")

# More concise with list comprehension
even_numbers = [num for num in numbers if num % 2 == 0]

Accumulating Results

# Sum of elements
numbers = [4, 7, 2, 9, 1, 5]
total = 0

for num in numbers:
    total += num

print(f"Sum: {total}")  # 28

# Building a new collection
words = ["hello", "world", "python"]
capitalized = []

for word in words:
    capitalized.append(word.capitalize())

print(capitalized)  # ['Hello', 'World', 'Python']

Processing File Data

# Reading a file line by line
with open('example.txt', 'r') as file:
    for line in file:
        line = line.strip()  # Remove leading/trailing whitespace
        print(line)

# Process CSV data
import csv
with open('data.csv', 'r') as file:
    csv_reader = csv.reader(file)
    for row in csv_reader:
        print(row)  # row is a list of values

Practice Exercises

Exercise 1: FizzBuzz

# Write a program that prints the numbers from 1 to 100.
# But for multiples of three print "Fizz" instead of the number
# and for the multiples of five print "Buzz".
# For numbers which are multiples of both three and five print "FizzBuzz".

# Your code here

Exercise 2: Nested Loop Pattern

# Write a program that prints the following pattern:
# *
# **
# ***
# ****
# *****

# Your code here

Exercise 3: Prime Number Checker

# Write a function that checks whether a number is prime.
# Then use it to find all prime numbers between 1 and 100.

# Your code here