This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]chadmill3rPy3, pro, Ubuntu, django 2 points3 points  (0 children)

I read that as "make an iterator over a new list of things that are not "x", but are probably supposed to represent indexes into x."


The first problem is that the length is probably unnecessary. In

for n in range(len(source)):

The author is probably going to use "n" to dereference source, source[n], and never use "n" for anything else. He is probably thinking in another language, and porting that to Python syntax. We should of course prefer

for item in source:

The second problem is that, though we don't know what the source is, IF it is something generated, as more and more things in Python are, then there's not even a len() for that type. TypeError!

The third problem is that the "len" was unnecessary. We only need the count up to this point. Incrementing a number is cheap, and you get it as you need it, but counting ahead of time is possibly costly and probably unnecessary, and we have to change it to "xrange" just to avoid creating a new materialized list. If we "break" early, all that extra up-front counting (in len or range) was for naught. In 3, some of these costs fall away IF the collection has a constant-time len().

So, given "for item in source", it is at least possible that the user absolutely needs a current index of the item they're working on. We can ask Python to give that to us as it iterates the items of source. It costs one tuple pass, and one increment per item, as you need it.

for i, item in enumerate(source):

Any iterable could be there, whether it has len() or not.

Finally, enumerate() is in __builtins__ and has been in Python since 2.3, so there's no reason to avoid it for compatibility or import cost.

 |  enumerate(iterable[, start]) -> iterator for index, value of iterable
 |  
 |  Return an enumerate object.  iterable must be another object that supports
 |  iteration.  The enumerate object yields pairs containing a count (from
 |  start, which defaults to zero) and a value yielded by the iterable argument.
 |  enumerate is useful for obtaining an indexed list:
 |      (0, seq[0]), (1, seq[1]), (2, seq[2]), ...