How to Use the Range Function Without a For Loop in Python
Why Bother Skipping the For Loop?
For loops are everywhere in Python. Most people reach for them automatically when they need to iterate with range(). But sometimes a for loop adds unnecessary verbosity, or you need a different pattern entirely.
This guide shows you every real alternative. No "embrace the journey" nonsense. Just the code that works.
The Methods at a Glance
| Method | Best For | Returns |
|---|---|---|
| List Comprehension | Creating transformed lists | List |
| map() | Applying a function to each item | Map object (lazy) |
| while loop | Manual control over iteration | None (side effects) |
| itertools | Advanced iteration patterns | Iterator |
| Walrus operator | Concise expressions | Varies |
List Comprehensions with range()
This is the most common replacement. You get a new list without writing a loop explicitly.
Standard for loop:
squares = []
for i in range(10):
squares.append(i ** 2)
Comprehension version:
squares = [i ** 2 for i in range(10)]
The comprehension is cleaner and faster. It handles the iteration internally without you writing for as a statement.
You can add conditions too:
even_squares = [i ** 2 for i in range(20) if i % 2 == 0]
Using map() with range()
map() applies a function to every item in an iterable. It doesn't need a for loop.
result = list(map(str, range(5)))
# ['0', '1', '2', '3', '4']
You can use map() with any function:
def process(x):
return x * 2 + 1
doubled = list(map(process, range(5)))
# [1, 3, 5, 7, 9]
One thing to note: map() returns a lazy iterator. You need to wrap it with list() if you want a concrete list. This is memory-efficient for large ranges.
The while Loop Approach
Technically a while loop isn't a for loop. It gives you manual control over the iteration counter.
i = 0
while i < 10:
print(i)
i += 1
This is useful when you need custom increment logic or want to break based on conditions that aren't tied to the iterator itself.
Most of the time, a for loop is cleaner. But if you're replacing a specific for pattern and need different behavior, while works.
itertools for Advanced Patterns
The itertools module has functions that work with range() without explicit for loops.
count and cycle
import itertools
# Combine range with count for custom sequences
combined = list(itertools.islice(
zip(range(5), itertools.count(start=10, step=5)),
5
))
# [(0, 10), (1, 15), (2, 20), (3, 25), (4, 30)]
filterfalse
import itertools
filtered = list(itertools.filterfalse(
lambda x: x % 2 == 0,
range(10)
))
# [1, 3, 5, 7, 9]
accumulate
import itertools
running_sum = list(itertools.accumulate(range(1, 6)))
# [1, 3, 6, 10, 15]
The Walrus Operator Trick
Python 3.8+ has the walrus operator (:=). It assigns and returns a value in the same expression. You can use it with range() in comprehensions.
# Print values while building a list
[print(y := x * 2) for x in range(5)]
# 0, 2, 4, 6, 8
This is concise but can get hard to read. Use it sparingly.
Unpacking with range()
You can use range() to generate indices, then unpack into variables.
data = [(1, 2), (3, 4), (5, 6)]
indices = range(len(data))
# Access via index without explicit for
first_elements = [data[i][0] for i in indices]
This doesn't eliminate iteration, but it uses range() differently than a typical for loop.
Getting Started: Which Method to Use
Pick based on what you need:
- Build a list — use list comprehension
- Apply a function — use
map() - Complex iteration logic — use
while - Advanced patterns — use
itertools - Side effects in expressions — use walrus operator
List comprehensions cover most cases. If you're reaching for itertools or the walrus operator, double-check that your code won't confuse whoever reads it next.
Common Mistakes
Forgetting list() around map(). It returns a lazy iterator, not a list.
Using walrus operators in list comprehensions that get assigned to variables. It's legal but confusing.
Overcomplicating things. If a simple for loop is clearer, use it. These alternatives exist for specific cases, not as replacements for every loop.