iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Python’s for loop does not inherently count. It takes items one at a time from an iterable; range() is one way to provide a sequence of integers. Once you separate those ideas, it is easier to choose between looping over values, positions, or a numeric progression.
What a Python for loop actually does
A for statement asks an iterable for its next item, assigns that item to the loop target, and runs the loop body. It repeats until there are no more items. For example:
for word in words:
print(word)
On each pass, word refers to the next item supplied by words. If the program needs the words themselves, this direct form is clearer than generating numbers and using them to look up the words. Python’s tutorial explains that its for statement iterates over sequence items in order; the language reference describes the loop target receiving successive items.
What range() contributes
range() supplies an arithmetic progression of integers. The one-argument form starts at zero and stops before its argument:
#1 Best Overall
for i in range(5):
print(i)
This loop produces 0, 1, 2, 3, and 4. The stop value, 5, is not included. That exclusive endpoint makes the number of values straightforward: range(5) has five values, just as a sequence of length five has indices 0 through 4.
With two or three arguments, the form is range(start, stop, step). The start is included, the stop is excluded, and the step sets the increment:
Rank #2
list(range(2, 10, 2))
# [2, 4, 6, 8]
A negative step counts downward when the start, stop, and step direction agree—for example, range(5, 0, -1) produces 5 through 1. The official control-flow tutorial documents the range boundaries and step behavior.
Choosing between direct iteration, enumerate(), and range()
Choose a loop form according to what the body needs. These patterns are useful in different situations, rather than one being universally right:
| What the loop needs | Pattern | Why |
|---|---|---|
| Each value | for item in items: |
Iterates directly over the supplied values. |
| Each value and its position | for index, item in enumerate(items): |
Provides the position and corresponding value together. |
| An integer progression, or positions without needing the values directly | for i in range(...): |
Supplies integers for counting or index-based work. |
Values only: loop over the sequence
Use for item in items when the item is what you will process. It avoids an unnecessary index lookup and makes the purpose visible.
Position and value: use enumerate()
If the loop needs both the index and item, use:
for index, item in enumerate(items):
print(index, item)
This yields each position alongside its value. The Python tutorial’s looping techniques section presents enumerate() for this purpose.
Index-only work: use range(len(items)) when appropriate
Sometimes the position is the useful part—for example, when comparing adjacent positions or updating items by index. In that case, an index loop can be appropriate:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
for index in range(len(items)):
print(index, items[index])
If you also need the item at each position, enumerate(items) usually expresses that intent more directly.
Best Value
A range is not a list
range(5) is a range object, not a prebuilt list containing five integers. It represents an immutable arithmetic sequence and provides successive values when iterated. If a list is specifically required—for example, to store or display the values as a list—convert it explicitly:
values = list(range(5))
The result is [0, 1, 2, 3, 4]. Otherwise, you can pass the range directly to a for loop. The Python tutorial describes range objects and their iteration behavior.
Common loop mistakes and cautions
- Expecting the stop value to appear:
range(10)gives ten values, 0 through 9, not 0 through 10. To include a particular endpoint in an integer progression, set the stop boundary one step beyond it when the step and bounds permit. - Assuming the loop target controls the next value: assigning a new value to
iinside a loop does not change what the iterator supplies on its next pass. The next item still comes from the iterable. - Changing a collection while iterating over it: adding or removing items during traversal can make the loop’s behavior difficult to reason about. The tutorial demonstrates iterating over a copy or building a new collection instead of changing the one being traversed.
For more detail on loop behavior and collection handling, see the Python tutorial’s control-flow section and data-structures looping techniques.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

