For-Loops

A for loop is used when you know how many times you want to run a block of code, or when you are moving through a sequence (like a list or string).

# Iterating over a list
guests = ["Alice", "Bob", "Charlie"]
for guest in guests:
    print(f"Hello, {guest}!")
    # Outputs: Hello, Alice
    # Hello, Bob
    # Hello, Charlie 

Iterating over a string goes character by character

for char in "Hello":
    print(char) # Outputs: H, e, l, l, o

The range() Function

While for loops are great for iterating over things you already have (like lists or strings), you often just need to run a block of code a specific number of times

Instead of creating a dummy list, we use the built-in range() function, which generates a sequence of integers on the fly for the loop to iterate over.

range(end): Starts at 0 and stops one step before the end value.

# Loops 0, 1, 2, 3, 4
for i in range(5):
    print(i) # Outputs: 0, 1, 2, 3, 4

range(start, end, step): Gives you more control over where you start and how much you increment each time.

# Counting from 1 to 10 with a step of 2
for i in range(1, 11, 2):
    print(i) # Outputs: 1, 3, 5, 7, 9

You should never modify a sequence (like removing items from a list) while you are iterating over it with a for-loop - it will cause unexpected behavior. Use a while-loop instead.

numbers = [1, 2, 3, 4, 5, 6]
# Goal: Remove all even numbers.

for n in numbers:
    if n % 2 == 0:
        numbers.remove(n)

print(numbers) 
# Outputs: [1, 3, 5, 6] 
# It failed to remove 4 and 6 because the list was changing size as the loop ran!

While-Loops

A while-loop repeatedly executes a block of code as long as a specific condition remains True. These are great if you want to keep working until the “to-do” list is empty.

todo_list = ["Wash dishes", "Buy groceries", "Call mom"]

while len(todo_list) > 0:
    current_task = todo_list.pop(0)  # Removes the first item from the list
    print(f"Now doing: {current_task}")

print("All done for the day!")

Watch out for infinite loops. If your condition never becomes False, the loop will run forever and likely crash your program.

count = 10

while count > 0:
    print(f"Counting down: {count}")
    # We forgot to do: count -= 1
    # Because 'count' stays 10, it is ALWAYS > 0.
    # This will run forever or until the memory runs out.

Break and Continue

Sometimes you need to bail out of a loop early or skip a specific iteration.

break: Immediately terminates the loop. Use this if you’ve already found the result you were looking for and don’t need to keep checking.

for num in range(10):
    if num == 5:
        break # Stops completely at 5 (The rest of the loop is skipped)
    print(num) # Outputs: 0, 1, 2, 3, 4

continue: Bypasses the rest of the current iteration and moves directly to the next one.

for num in range(5):
    if num == 3:
        continue # Skips 3 and goes to 4
    print(num) # Outputs: 0, 1, 2, 4

Nested Loops

When dealing with complex data like a Weekly Workout Plan, you’ll use nested loops (a loop inside another loop).

For every one step in your outer loop, the inner loop runs its entire cycle.

days = ["Monday", "Wednesday", "Friday"]
exercises = ["Pushups", "Squats", "Plank"]

for day in days:
    print(f"--- {day} ---")
    for exercise in exercises:
        print(f"Executing: {exercise}")
        # Outputs:
        # --- Monday ---
        # Executing: Pushups
        # Executing: Squats
        # Executing: Plank
        # --- Wednesday ---
        # Executing: Pushups
        # Executing: Squats
        # Executing: Plank
        # --- Friday ---
        # Executing: Pushups
        # Executing: Squats
        # Executing: Plank

Do-While

In some other languages, a do-while loop ensures the code runs at least once before checking the condition. Python doesn’t have a dedicated do-while keyword, but we can replicate it perfectly using while True and a break.

# This will keep asking for a password until it's correct
# It runs the "input" code FIRST, then checks the condition.
secret_password = "python101"

while True:
    guess = input("Enter the password: ")
    
    if guess == secret_password:
        print("Access Granted!")
        break
    else:
        print("Wrong! Try again.")

List Comprehensions

If you are using a loop just to create a new list (like doubling numbers or formatting names), you can use a List Comprehension.

It’s essentially a for-loop inside square brackets.

The syntax looks like this: [expression for item in sequence]

# The "Traditional" way (3 lines)
numbers = [1, 2, 3, 4]
squares = []

for n in numbers:
    squares.append(n * n)

# The "Pythonic" way (1 line)
squares = [n * n for n in numbers]

print(squares) # [1, 4, 9, 16]

Tuple Comprehensions

While you can use square brackets [] for lists, you might think using () would create a “Tuple Comprehension.”

In Python, (n * n for n in numbers) actually creates something called a Generator (concept we will cover later). If you want to create a Tuple in one line, you have to explicitly tell Python to convert it:

numbers = [1, 2, 3, 4]

# One-liner for a Tuple
squares_tuple = tuple(n * n for n in numbers)

print(squares_tuple) # (1, 4, 9, 16)