enumerate() быстрее, когда вы хотите повторно обращаться к списку/итерируемым элементам по их индексу. Когда вам просто нужен список индексов, быстрее использовать len() и range().

Функция range() часто бывает полезна при переборе набора целых чисел:

for n in range(200):
    print(n)

#

for n in range(50, 110):
    print(n)

или список строк:

for number in ["one", "two", "three", "four"]:
    print(number)

Теперь предположим, что вы хотите выполнить итерацию по списку чисел, а также показать индекс текущего элемента в списке. Используя range(), это можно сделать так:

numbers = ["one", "two", "three", "four"]

for i in range(len(numbers)):
    number = numbers[i]
    print('index : {0} - number : {1}'.format(i, number))

# Output:
# index : 0 - number : one
# index : 1 - number : two
# index : 2 - number : three
# index : 3 - number : four

Он выполняет свою работу, но не очень pythonic. Вы должны получить длину списка, чтобы отслеживать индекс, а затем индексировать массив, чтобы получить текущий результат, что делает код более подробным и трудным для чтения.

Вот почему enumerate() лучше

numbers = ["one", "two", "three", "four"]

for i, number in enumerate(numbers):
    print('index : {0} - number : {1}'.format(i, number))

# Output:
# index : 0 - number : one
# index : 1 - number : two
# index : 2 - number : three
# index : 3 - number : four

Нумерацию также можно настроить так, чтобы она начиналась с любого желаемого номера.

numbers = ["one", "two", "three", "four"]

for i, number in enumerate(numbers, 10):
    print('index : {0} - number : {1}'.format(i, number))

# Output:
# index : 10 - number : one
# index : 11 - number : two
# index : 12 - number : three
# index : 13 - number : four

Спасибо вам всем :)