Stop Using range(len()) in Python — Use This Instead
I’ve seen even experienced devs overuse range(len()). Here’s how to fix it.

I thought range(len())
was the standard way to loop over indexes — until I found a cleaner, smarter Pythonic alternative.
Stop Using range(len())
in Python — Use This Instead
If you’ve been using Python for any reasonable amount of time, there’s a good chance you’ve written something like this:
my_list = ['apple', 'banana', 'cherry']
for i in range(len(my_list)):
print(f"{i}: {my_list[i]}")
It works. It’s readable — sort of. But it’s not very Pythonic.
In fact, this is one of the classic anti-patterns that many developers (especially those coming from C, Java, or C++) tend to carry into Python.
And it’s time we talk about why you should stop using range(len(...))
— and what you should use instead.
The Problem With range(len(...))
Using range(len(...))
couples index access with the container. It forces you to manage the loop counter manually and makes your code more error-prone.
Consider what happens when you refactor my_list
into a dictionary, or worse, if your list has dynamic content. You’re now stuck rewriting your loop logic.
But more importantly: Python offers a better, cleaner, and more expressive way.
Meet enumerate()
: The Pythonic Way
Instead of this:
for i in range(len(my_list)):
print(f"{i}: {my_list[i]}")
Do this:
for index, value in enumerate(my_list):
print(f"{index}: {value}")
Isn’t that cleaner?
Why enumerate()
Is Better
- Readable: It clearly states you’re iterating with both the index and the value.
- Safe: It avoids accidental index errors.
- Pythonic: It embraces Python’s core philosophy — simplicity and elegance.
“There should be one– and preferably only one –obvious way to do it.” — The Zen of Python
A Real-World Example
Imagine you’re comparing two lists element by element:
list_a = ['a', 'b', 'c']
list_b = ['x', 'y', 'z']
for i in range(len(list_a)):
print(f"{list_a[i]} -> {list_b[i]}")
Now, try the same with enumerate()
:
for i, value in enumerate(list_a):
print(f"{value} -> {list_b[i]}")
Still not perfect, right?
Here’s the real Pythonic way using zip()
:
for a, b in zip(list_a, list_b):
print(f"{a} -> {b}")
Boom! Cleaner. Simpler. No indexing.
Bonus: Custom Start Index
If you need to start indexing from a number other than zero, enumerate()
supports that too:
for index, fruit in enumerate(my_list, start=1):
print(f"{index}. {fruit}")
Output:
1. apple
2. banana
3. cherry
No more +1
hacks. Python already has your back.
When Should You Use range(len(...))
?
To be fair, there are valid use cases.
You should use range(len(...))
only if:
- You only need the index, not the value.
- You’re modifying the list by index.
- You’re working with multiple sequences and need fine control over indices.
But these are rarer than most people think.
Final Thoughts
If you’re aiming to write clean, maintainable, and Pythonic code, it’s time to retire your old habit of writing range(len(...))
. Use enumerate()
— or better yet, rethink whether you need the index at all.
Remember: just because something works doesn’t mean it’s the best way to write it.
If you enjoyed this, follow me for more Python tips that save time, clean up your code, and make you look like a pro.
