Why is "for i in range(len(arr))" considered un-Pythonic?
Asked Answered
D

1

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.

Doubleminded answered 19/8, 2020 at 17:25 Comment(2)
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):.Fosdick
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"?Babism
E
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.

Earthquake answered 19/8, 2020 at 17:25 Comment(2)
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?Doubleminded
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?Earthquake

© 2022 - 2024 — McMap. All rights reserved.