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. -- http://mail.python.org/mailman/listinfo/python-list