Loops in Python: for, while, and Beyond

Loops are control flow statements that allow you to execute a block of code repeatedly. This is fundamental to programming, enabling automation, data processing, and efficient task execution. Python offers two primary types of loops: for loops and while loops.



1. The for Loop: Iterating Over Sequence

The for loop is used to iterate over a sequence (like a list, tuple, string, or range) or other iterable objects. It executes a block of code once for each item in the sequence.

OR

The for loop in Python is used to repeat a block of code for every element in a sequence (like a list, tuple, string, or range).

It helps you automate repetitive tasks.


Syntax:

for variable in iterable:
    # Code block to execute for each item
    # (Indented)

Key Points :


Examples:

1.1. Iterating over a list:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(f"I like {fruit}.")

# Output:
I like apple.
I like banana.
I like cherry.


1.2. Iterating over a string (characters):

name = "Python"
for char in name:
    print(char)

# Output:
P
y
t
h
o
n


1.3. Iterating using range( ) (Numbers):

range( ) is a built-in function that generates a sequence of numbers. It's commonly used with for loops.

# From 0 to 4 (exclusive of 5)
for i in range(5):
    print(i) # Output: 0, 1, 2, 3, 4
print("-" * 10)
# From 2 to 5 (exclusive of 6)
for i in range(2, 6):
    print(i) # Output: 2, 3, 4, 5
print("-" * 10)
# From 1 to 10, incrementing by 2
for i in range(1, 11, 2):
    print(i) 

# Output: 1, 3, 5, 7, 9


1.4. Iterating over a dictionary:

student_scores = {"Alice": 95, "Bob": 88, "Charlie": 72}
print("Iterating over keys:")
for name in student_scores: # Or student_scores.keys()
    print(name)
print("\nIterating over values:")
for score in student_scores.values():
    print(score)
print("\nIterating over key-value pairs:")
for name, score in student_scores.items(): # Unpacking the (key, value) tuple
    print(f"{name}: {score}")

# Output:
Iterating over keys:
Alice
Bob
Charlie

Iterating over values:
95
88
72

Iterating over key-value pairs:
Alice: 95
Bob: 88
Charlie: 72


2. The while Loop: Repeating Until a Condition is Met

The while loop repeatedly executes a block of code as long as a specified condition is True.

OR

While loop will run a piece of code while a condition is True. it is based on a boolean condition.


Syntax:

while condition:
    # Code block to execute as long as condition is True
    # (Indented)

Key Points :


Examples:

2.1. Counting up to a number :

count = 1
while count <= 5:
    print(count)
    count += 1 # Increment count to eventually make the condition False

# Output:
1
2
3
4
5


2.2. User input until a specific value :

user_input = ""
while user_input != "quit":
    user_input = input("Enter something (type 'quit' to exit): ")
    if user_input != "quit":
        print(f"You entered: {user_input}")
    
# Sample Output:
Enter something (type 'quit' to exit): Hello
You entered: Hello
Enter something (type 'quit' to exit): 123
You entered: 123
Enter something (type 'quit' to exit): quit

#No output is printed after "quit" because the condition user_input != "quit" fails, and the loop exits.

Explanation :



2.3. Infinite Loop (and how to avoid/handle it) :

An infinite loop occurs when the loop's condition never becomes False. This will freeze your program.

# DANGER: This is an infinite loop!
# while True:
#     print("This will print forever...")

# To stop an infinite loop in most environments (like a terminal), press Ctrl+C.

Always ensure your while loop has a mechanism to terminate.



3. Loop Control Statements

Python provides specific statements to alter the normal execution flow of loops:



3.1. break Statement :

The break statement immediately terminates the loop (both for and while) and transfers control to the statement immediately following the loop.


Examples:

for i in range(1, 10):
    if i == 5:
        print("Breaking loop at 5!")
        break
    print(i)
print("Loop finished.")

# Output:
1
2
3
4
Breaking loop at 5!
Loop finished.


3.2. continue Statement :

The continue statement skips the rest of the current iteration of the loop and proceeds to the next iteration.

Examples:

for i in range(1, 6):
    if i % 2 == 0: # If i is even
        print(f"Skipping even number: {i}")
        continue # Skip the rest of this iteration
    print(f"Odd number: {i}")

# Output:
Odd number: 1
Skipping even number: 2
Odd number: 3
Skipping even number: 4
Odd number: 5


3.3. pass Statement :

The pass statement is a null operation; nothing happens when it executes. It's often used as a placeholder where syntax requires a statement but you don't want any code to execute yet.


Examples:

# Placeholder for future code
for item in some_list:
    if item.is_valid():
        pass # TODO: Implement validation logic here later
    else:
        print("Invalid item found.")


4. else Clause with Loops (Advanced)

Both for and while loops can have an optional else block. The code in the else block executes only if the loop completes without encountering a break statement.




Example 4.1: for loop with else :

numbers = [1, 3, 5, 7, 9]
search_item = 6 # Item not in list
for num in numbers:
    if num == search_item:
        print(f"{search_item} found in the list!")
        break # This break will prevent the else block from executing
else: # Executes if loop completes normally (no break)
    print(f"{search_item} not found in the list.")
print("-" * 20)
numbers = [1, 3, 5, 7, 9]
search_item = 5 # Item is in list
for num in numbers:
    if num == search_item:
        print(f"{search_item} found in the list!")
        break
else:
    print(f"{search_item} not found in the list.")

# Output:
6 not found in the list.
--------------------
5 found in the list!


Example 4.2: while loop with else :

count = 0
while count < 3:
    print(f"Count is {count}")
    count += 1
else: # Executes because the loop finished naturally (count reached 3)
    print("While loop finished normally.")
print("-" * 20)
count = 0
while True: # An infinite loop without a break
    print(f"Count is {count}")
    count += 1
    if count == 2:
        print("Breaking the while loop!")
        break # This break will prevent the else block from executing
else:
    print("While loop finished normally.") # This will NOT print

# Output:
Count is 0
Count is 1
Count is 2
While loop finished normally.
--------------------
Count is 0
Count is 1
Breaking the while loop!

Use Case for else with loops: This else clause is particularly useful for "search" loops, where you want to perform an action if an item is not found after checking all possibilities.



5. Nested Loops (Advanced Basic)

You can place a loop inside another loop. This is called nesting. Nested loops are commonly used for tasks like iterating over 2D data structures (matrices), or generating combinations.



Example 5.1: Printing a multiplication table :

print("Multiplication Table:")
for i in range(1, 4): # Outer loop for rows
    for j in range(1, 4): # Inner loop for columns
        print(f"{i} * {j} = {i*j}", end="\t") # '\t' for tab spacing
    print() # New line after each row

# Output:
Multiplication Table:
1 * 1 = 1	1 * 2 = 2	1 * 3 = 3
2 * 1 = 2	2 * 2 = 4	2 * 3 = 6
3 * 1 = 3	3 * 2 = 6	3 * 3 = 9


Example 5.2: Generating coordinate pairs :

for x in range(3): # x values: 0, 1, 2
    for y in range(2): # y values: 0, 1
        print(f"({x}, {y})")

# Output:
(0, 0)
(0, 1)
(1, 0)
(1, 1)
(2, 0)
(2, 1)

Key point for nested loops: The inner loop completes all its iterations for each single iteration of the outer loop.



6. Loop Optimizations and Advanced Techniques

6.1. enumerate( ) for Index and Value :

When you need both the index and the value while iterating, enumerate( ) is highly efficient and Pythonic.


Example :

my_list = ["apple", "banana", "cherry"]
for index, value in enumerate(my_list):
    print(f"Index {index}: {value}")

# Output:
Index 0: apple
Index 1: banana
Index 2: cherry


6.2. zip() for Parallel Iteration :

zip( ) combines multiple iterables element-wise. It stops when the shortest iterable is exhausted.


Example :

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 22]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old.")

# Output:
Alice is 25 years old.
Bob is 30 years old.
Charlie is 22 years old.


6.3. List Comprehensions (Advanced for loop shortcut) :

A powerful and concise way to create lists based on existing iterables, often replacing simple for loops.


Syntax :

Mapping: [expression for item in iterable]

Filtering: [expression for item in iterable if condition]

# Traditional loop to square numbers
squares_loop = []
for i in range(5):
    squares_loop.append(i**2)
print(f"Squares (loop): {squares_loop}") # Output: [0, 1, 4, 9, 16]
# List comprehension for squares
squares_comp = [i**2 for i in range(5)]
print(f"Squares (comprehension): {squares_comp}") # Output: [0, 1, 4, 9, 16]
# Filtering even numbers
even_numbers = [num for num in range(10) if num % 2 == 0]
print(f"Even numbers: {even_numbers}") # Output: [0, 2, 4, 6, 8]


6.4. Dictionary and Set Comprehensions :

Similar to list comprehensions, for creating dictionaries and sets.

# Dictionary comprehension
word = "hello"
char_counts = {char: word.count(char) for char in set(word)}
print(f"Character counts: {char_counts}") # Output: {'e': 1, 'o': 1, 'l': 2, 'h': 1}
# Set comprehension
unique_squares = {x**2 for x in [1, 2, 2, 3, 4, 4, 5]}
print(f"Unique squares: {unique_squares}") # Output: {1, 4, 9, 16, 25}


6.5. Generator Expressions (Lazy Evaluation) :

Similar to list comprehensions but use parentheses ( ) instead of square brackets [ ]. They create generators, which are iterators that produce values one at a time on demand (lazy evaluation), saving memory for large datasets.

# List comprehension (creates entire list in memory)
list_of_squares = [x*x for x in range(1000000)]
# Generator expression (creates values on the fly)
gen_of_squares = (x*x for x in range(1000000))
# You can iterate over a generator
for sq in gen_of_squares:
    # process sq
    if sq > 100:
        break


When to choose for vs. while?

for loop: Use when you know in advance how many times you need to loop, or when you need to iterate over a collection of items (lists, strings, ranges, etc.). It's ideal for definite iteration.

while loop: Use when the number of iterations is unknown and depends on a condition being met. It's ideal for indefinite iteration, such as waiting for user input, reading from a file until an end-of-file marker is reached, or simulating a game loop.



Common Pitfalls :

Infinite Loops: Always ensure your while loop condition eventually becomes False.

Modifying a list while iterating over it: This can lead to unexpected behavior. If you need to modify a list, it's often safer to iterate over a copy or build a new list.

my_list = [1, 2, 3, 4]
# DON'T DO THIS without careful consideration!
# for item in my_list:
#     if item == 2:
#         my_list.remove(item) # Modifies list during iteration!
# Output might be [1, 3, 4] but often skips items.

# Instead, create a new list or iterate over a copy:
new_list = [item for item in my_list if item != 2]
# Or:
# for item in list(my_list): # Iterate over a copy

Off-by-one errors with range( ) or while conditions: Carefully check your start, stop, and step values in range( ), and boundary conditions in while
loops ( <= vs < ).

Incorrect Indentation: Python relies heavily on indentation to define code blocks. Incorrect indentation will cause IndentationError or logical errors.