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:

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.