for i in range() anti-pattern [was Re: trouble writing results to files]

Steven D'Aprano steve at REMOVE.THIS.cybersource.com.au
Wed Nov 29 19:38:32 EST 2006


On Wed, 29 Nov 2006 17:00:30 +0100, Fredrik Lundh wrote:

> Neil Cerutti wrote:
> 
>>> BTW, iterating over range(len(a)) is an anti-pattern in Python.
>> 
>> Unless you're modifying elements of a, surely?
> 
> and needs to run on a Python version that doesn't support enumerate.

This isn't meant as an argument against using enumerate in the common
case, but there are circumstances where iterating with an index variable
is the right thing to do. "Anti-pattern" tends to imply that it is always
wrong.

The advantage of enumerate disappears if you only need to do something to
certain items, not all of them:

>>> alist = list("abcdefghij")
>>> for i in xrange(3, 7, 2):
...     print i, alist[i]
...
3 d
5 f

Nice and clear. But this is just ugly and wasteful:

>>> for i,c in enumerate(alist):
...     if i in xrange(3, 7, 2):
...             print i, c
...
3 d
5 f

although better than the naive alternative using slicing, which is just
wrong:

>>> for i,c in enumerate(alist[3:7:2]):
...     print i, c
...
0 d
1 f

The indexes point to the wrong place in the original, non-sliced list, so
if you need to modify the original, you have to adjust the indexes by hand:

>>> for i,c in enumerate(alist[3:7:2]):
...     print 2*i+3, c
...
3 d
5 f

And remember that if alist is truly huge, you may take a performance hit
due to duplicating all those megabytes of data when you slice it. If you
are modifying the original, better to skip making a slice.

I wrote a piece of code the other day that had to walk along a list,
swapping adjacent elements like this:

for i in xrange(0, len(alist)-1, 2):
    alist[i], alist[i+1] = alist[i+1], alist[i] 


The version using enumerate is no improvement:

for i, x in enumerate(alist[0:len(alist)-1:2]):
    alist[i*2], alist[i*2+1] = alist[i*2+1], x


In my opinion, it actually is harder to understand what it is doing.
Swapping two items using "a,b = b,a" is a well known and easily recognised
idiom. Swapping two items using "a,b = b,c" is not.


-- 
Steven.




More information about the Python-list mailing list