Concepts / For Loops and Range

For Loops and Range

A for loop lets you repeat a block of code multiple times, once for each item in a sequence.

  • Programming
Interactive lab

Try it: What a for Loop Hands You

What a Python for loop gives its loop variable from each kind of iterable: the characters of a string, the positions from range(len(word)), the elements of a list, (index, item) pairs from enumerate(), the numbers of range(start, stop, step), a dict's keys, its .values() and its .items() tuples unpacked into key, val, the inner lists of a nested list and the values an inner loop visits; and why removing items from a list while looping over it skips the next item, while looping over a copy nums[:] does not.

How it works

  1. The for statement asks the object for an iterator, then calls next() on it once per pass.
  2. Each next() result is bound to the loop variable (a tuple result such as ('a', 10) or (0, 'red') is unpacked into two names), and the indented body runs once with it.
  3. A string gives characters, a list gives element values (not positions), range() computes start, start + step, … stopping before stop, and a dict gives its keys in insertion order (.values() the values, .items() key-value tuples).
  4. A nested list's inner list is one element of the outer loop; a second, inner for loop is needed to visit the values inside it.
  5. A list iterator only remembers a position number into the live list: removing an item shifts the later items left, so the item that slides into the passed position is skipped. Looping over a copy (nums[:]) keeps the positions fixed.
  6. When next() has nothing left the loop ends (StopIteration) and the loop variable keeps its last value; an empty iterable runs the body zero times.

Default run (10 steps): A 3-line program. Step through it: each pass of the for loop asks the iterator for its next item, binds the loop variable to it and runs the indented body once. … Done: the loop body ran 3 times. Output: red | green | blue.

Simplified: The programs are twelve fixed templates: you choose the loop and edit only its data (a short string, list items that are words or integers, key: value pairs with word keys and integer values, range numbers from -20 to 20, up to 4 rows of integers, up to 10 numbers). Nothing you type is executed: the lab's own small parsers turn it into literals, and a model of CPython's iterator protocol written for these loops runs the program. Every program was also run in CPython 3.12 under sys.settrace, and the lab reproduces the variables before every line, the printed output, the final variables and the error.

Educational simulation

Loading the simulation…

What Does a For Loop Do?

A for loop lets you repeat a block of code multiple times, once for each item in a sequence. Instead of writing the same code over and over, you write it once and let the loop handle the repetition. The key insight is that the loop variable (often called i) takes on a different value each time through the loop, and you can use that value inside your code block.

The most common way to create a sequence of numbers to loop over is the range() function. When you write for i in range(1, 5), Python creates a sequence of numbers and your loop visits each one in order, assigning it to i and running your code block.

How Range Generates Numbers

The range() function is a built-in Python tool that generates a sequence of numbers. It does not create all the numbers at once and store them in memory. Instead, it generates one number at a time, on demand, as your for loop requests each one. This is efficient, especially when you need a very long sequence.

To see all the numbers range() would produce, you can convert it to a list using list(range()). For example, list(range(1, 5)) shows you [1, 2, 3, 4]. But inside a for loop, you do not need to do this conversion; the loop automatically gets each number one at a time.

Definition

range(start, stop) generates integers beginning at start and ending just before stop. The start value is included; the stop value is excluded.

range(1, 5)start=1, stop=51first iteration2second iteration3third iteration4fourth iteration5NOT included (stop isexcluded)generatesgeneratesgeneratesgeneratesdoes NOT generate
What values does range(1, 5) actually produce, and in what order does the loop visit them?

Stepping Through a For Loop

Let us trace through a concrete example to see exactly what happens as a for loop runs. Understanding this step-by-step execution is the key to mastering loops.

Worked example

Tracing for i in range(1, 5): print(i)

What does this code print, and what is the value of i at each step?

  1. 1
    Iteration 1

    Python starts the loop and assigns i = 1 (the first value from range(1, 5)). The code block print(i) runs, printing 1.

  2. 2
    Iteration 2

    Python moves to the next value in the sequence and assigns i = 2. The code block runs again, printing 2.

  3. 3
    Iteration 3

    Python assigns i = 3 and runs the code block, printing 3.

  4. 4
    Iteration 4

    Python assigns i = 4 and runs the code block, printing 4.

  5. 5
    Loop ends

    range(1, 5) has no more values to produce (5 is excluded). The loop exits and any code after the loop runs next.

Result

The output is: 1 2 3 4 (each on its own line)

Before loop startsi does not exist yeti = 1print(i) outputs: 1i = 2print(i) outputs: 2i = 3print(i) outputs: 3i = 4print(i) outputs: 4Loop endsi still equals 4 (lastvalue assigned)range assigns first valuenext iterationnext iterationnext iterationno more values
How does the variable i change its value with each iteration, and what is it at each step?

Controlling Range with Start, Stop, and Step

The range() function accepts up to three parameters: start, stop, and step. Understanding how each one works gives you precise control over which numbers your loop visits.

Definition

range(stop) generates integers from 0 up to (but not including) stop. This is the simplest form.

Definition

range(start, stop) generates integers from start up to (but not including) stop, incrementing by 1 each time.

Definition

range(start, stop, step) generates integers from start up to (but not including) stop, incrementing by step each time. The step can be negative to count backwards.

CodeWhat it producesExplanation
range(5)[0, 1, 2, 3, 4]Starts at 0 (default), stops before 5, step is 1 (default)
range(2, 6)[2, 3, 4, 5]Starts at 2, stops before 6, step is 1
range(0, 10, 2)[0, 2, 4, 6, 8]Starts at 0, stops before 10, increments by 2 each time
range(5, 0, -1)[5, 4, 3, 2, 1]Starts at 5, stops before 0, decrements by 1 each time (negative step)

Common range() patterns and their output

The For...Else Clause

Python allows you to attach an else clause to a for loop. The code in the else block runs after the loop completes normally (that is, when the loop finishes all its iterations without hitting a break statement). This is useful when you want to execute code only if the loop ran to completion.

Enter for loopMore items insequence?Run loop bodybreak statement?Exit loop (skip else)Loop completesnormallyRun else blockContinue after loopyesyesno (loop again)no
When does the else block execute, and how does the loop exit path determine whether it runs?
python
Output (expected)
1
2
3
4
The for loop is over

In this example, the loop runs through all four iterations (1, 2, 3, 4), and after the last iteration completes, the else block executes and prints 'The for loop is over'. If the loop had encountered a break statement, the else block would have been skipped.

For Loops Work with Any Sequence

While range() is the most common way to generate a sequence of numbers, the for loop works with any sequence. You can loop over lists, strings, tuples, and other sequence types. The loop variable takes on each element of the sequence, one at a time, and you can use it in your code block.

This flexibility is one of the most powerful features of for loops in Python. Whether you are iterating over numbers from range(), items in a list, or characters in a string, the same loop structure applies. We will explore this idea in detail in later chapters when we cover data structures like lists and strings.

Common Mistakes with For Loops and Range

  • Common mistake

    Forgetting that range(stop) excludes the stop value

    What it looks like
    for i in range(5): print(i) prints 0, 1, 2, 3, 4 — not 0 through 5
    Why it fails

    The stop parameter is exclusive. range(5) means 'up to but not including 5'.

    Do this instead

    If you want to include 5, use range(6) instead.

  • Common mistake

    Confusing range(start, stop) with range(stop, start)

    What it looks like
    for i in range(5, 1): print(i) produces no output (empty sequence)
    Why it fails

    range(5, 1) means 'start at 5, go up to but not including 1'. Since 5 is already past 1, there are no values to generate.

    Do this instead
    Use range(5, 1, -1) to count backwards from 5 to 2.
  • Common mistake

    Assuming the loop variable i exists before the loop starts

    What it looks like
    print(i) before the loop runs will raise a NameError if i has not been assigned elsewhere
    Why it fails

    The loop variable is created by the for statement itself, on the first iteration.

    Do this instead

    Only use the loop variable inside the loop body or after the loop has run at least once.

  • Common mistake

    Using list(range()) inside a loop when you do not need to

    What it looks like
    for i in list(range(1000000)): creates the entire list in memory before the loop starts
    Why it fails

    This wastes memory. range() generates values on demand, which is more efficient.

    Do this instead

    Use for i in range(1000000) directly; the loop will request each value as needed.

Practice: Writing Your Own For Loops

EASY

Write a for loop that prints the numbers 10, 20, 30, 40, 50. Use range() with appropriate start, stop, and step parameters.

Hints
  • You want to start at 10 and go up to (but not including) 60.
  • The step should be 10 to increment by 10 each time.
  • The code should be: for i in range(10, 60, 10): print(i)
MEDIUM

Write a for loop that counts backwards from 5 to 1 and prints each number. Then add an else clause that prints 'Countdown complete!' after the loop finishes.

Hints
  • Use a negative step to count backwards.
  • range(5, 0, -1) will give you 5, 4, 3, 2, 1.
  • The else block should be at the same indentation level as the for statement.
MEDIUM

Predict: What does this code print? for i in range(3): print(i * 2)

Hints
  • range(3) produces 0, 1, 2.
  • For each value of i, you print i * 2.

Key Takeaways

  1. 1
    A for loop repeats a block of code once for each item in a sequence, with the loop variable taking on each value in turn.
  2. 2
    range() generates a sequence of numbers on demand (one at a time), not all at once. Use list(range()) only if you need to see all values immediately.
  3. 3
    range(start, stop) includes start but excludes stop. range(start, stop, step) lets you control the increment or decrement.
  4. 4
    The loop variable persists after the loop ends and retains the value of the last iteration.
  5. 5
    A for...else clause runs only if the loop completes normally (without hitting a break statement).
  6. 6
    For loops work with any sequence type, not just range(). This makes them powerful for iterating over lists, strings, and other data structures.

At a glance

  • For loops repeat a code block for each item in a sequence, with the loop variable changing on each iteration.
  • range(start, stop, step) generates numbers efficiently on demand; the stop value is always excluded.
  • Trace through loops step-by-step to understand how the loop variable changes and when the code block runs.
  • The for...else clause executes only when the loop completes normally, not when a break statement exits early.
  • For loops work with any sequence type, making them a fundamental tool for iteration in Python.

Related concepts

More concepts starting with F