While the latter is definitiely the way to go as long as it fits your needs since its clear and pythonic, there are cases where you really need the index of the element.
One example are sorting algorithms, like this BubbleSort here (src):
def bubbleSort(arr):
n = len(arr)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
# traverse the array from 0 to n-i-1
# Swap if the element found is greater
# than the next element
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
Here the list indices of sequential elements are used to swap their positions in the list if their sort order is incorrect, while the position in the list is something the pure values of the elements in a for elem in arr
loop don't have any connection to anymore. Therefore in such cases you won't get around using the range
over the list's len
or similar, so that's not un-pythonic by defintion.
Last but not least, a good combination if you need both the index and the value is Python's enumerate
.
for index, value in enumerate(arr):
print(index, value)
Although one could use it in the above BubbleSort example, you'd start mixing value
variables with arr[index]
expressions, which is not a good idea for the readability of the code. So here, too, it depends very much on the situation if it makes sense to use the one construct or the other, there's no definite choice.