5

Edit: I want to clarify that I am asking here about situations when the index is explicitly required. I know that for item in items is better when it is not required. I have a long term habit of thinking of list items as my_list[i] or arr[i]. I find seeing the name of the list and the index next to each other very clear and helpful. So my question is really whether there is any advantage in changing the way I think about index and value to fit the way enumerate works.

As the title says. I have read many answers saying for i in range(len(arr)) is bad, but not heard a good reason as to why this is the case. One argument is that it is "un-Pythonic", but it looks pretty Pythonic superficially, compared to the c-style versions.

Since enumerate has an additional argument which is sometimes not needed, I'm confused as to the advantage, as increased simplicity doesn't seem guaranteed. I would be like to hear more about why I should avoid for i in range(len(arr)), or whether it is in fact just down to personal preference.

Robin Andrews
  • 3,514
  • 11
  • 43
  • 111
  • 5
    Because you rarely need it. How often do you want _just_ the index of the items? Generally you either _only_ want the items, in which case `for item in items:`, or you _also_ (but not only) need the index, in which case `for index, item in enumerate(items):`. – jonrsharpe Aug 19 '20 at 17:30
  • I have wondered about this as well. @jonrsharpe, I agree if you are using the index to access the array within the loop then enumerate is a much better option. But in the case that you do only need the index, then is it still "bad"? – dshanahan Aug 19 '20 at 17:34

1 Answers1

6

Iterating over a list directly is simpler.

for x in some_list:
    print(x)

versus

for i in range(len(some_list)):
    print(some_list[i])

If you do need the index, you can use enumerate (even if you don't care about the value at that index, though such uses cases are rare):

indices_of_positive = [i for i, x in enumerate(some_list) if x > 0]

versus

indices_of_positive = [i for i in range(len(some_list)) if some_list[i] > 0]

Note that enumerate doesn't require the iterable to support the length protocol.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • I have edited the question to exclude cases where `for item in items` would be suitable, because that is clear to me. So so far I have "enumerate doesn't require the iterable to support the length protocol." as a possible advantage. Are there any more? – Robin Andrews Aug 20 '20 at 05:46
  • It's more direct. Why iterate over indices when the only reason to use the index is to get an item of the list, when you can get the item directly via iteration? – chepner Aug 20 '20 at 11:28