Требуется только индекс: перечислять или (x) диапазон?

Если я хочу использовать только индекс внутри цикла, лучше ли использовать функцию range/xrange в сочетании с len()

a = [1,2,3]
for i in xrange(len(a)):
    print i 

или enumerate? Даже если я вообще не буду использовать p?

for i,p in enumerate(a):
    print i    

Ответы

Ответ 1

Я бы использовал enumerate, поскольку он более общий - например, он будет работать с итерами и последовательностями, а накладные расходы для просто возврата ссылки на объект - не такая большая сделка - пока xrange(len(something)) хотя (мне ) более легко читаемый, поскольку ваше намерение - разломит объекты без поддержки len...

Ответ 2

Это редкое требование - единственная информация, используемая в контейнере, - его длина! В этом случае я бы действительно сделал этот факт явным и использовал первую версию.

Ответ 3

Использование xrange с len - довольно распространенный вариант использования, поэтому да, вы можете использовать его, если вам нужно только получить доступ к значениям по индексу.

Но если вы предпочитаете использовать перечисление по какой-либо причине, вы можете использовать знак подчеркивания (_), это просто часто встречающаяся запись, которая показывает, что вы не будете использовать эту переменную каким-либо значимым образом:

for i, _ in enumerate(a):
    print i

Там также есть ошибка, которая может произойти с использованием подчеркивания (_). Также часто называют "перевод" функций как _ в библиотеках и системах i18n, поэтому остерегайтесь использовать его с gettext или какой-либо другой библиотекой такого типа (thnks to @lazyr).

Ответ 4

xrange должен быть немного быстрее, но перечисление будет означать, что вам не нужно менять его, когда вы понимаете, что вам нужно p afterall

Ответ 5

Основываясь на вашем примере кода,

res = [[profiel.attr[i].x for i,p in enumerate(profiel.attr)] for profiel in prof_obj]

Я бы заменил его на

res = [[p.x for p in profiel.attr] for profiel in prof_obj]

Ответ 6

Я написал это, потому что я хотел проверить его. Таким образом, это зависит от того, нужны ли вам значения для работы.

код:

testlist = []
for i in range(10000):
    testlist.append(i)

def rangelist():
    a = 0
    for i in range(len(testlist)):
        a += i
        a = testlist[i] + 1   # Comment this line for example for testing

def enumlist():
    b = 0
    for i, x in enumerate(testlist):
        b += i
        b = x + 1   # Comment this line for example for testing

import timeit
t = timeit.Timer(lambda: rangelist())
print("range(len()):")
print(t.timeit(number=10000))
t = timeit.Timer(lambda: enumlist())
print("enum():")
print(t.timeit(number=10000))

Теперь вы можете запустить его и, скорее всего, получите результат, который перечислит() быстрее. Когда вы комментируете источник в a = testlist[i] + 1 и b = x + 1, вы увидите диапазон (len()) быстрее.

Для кода выше я получаю:

range(len()):
18.766527627612255
enum():
15.353173553868345

Теперь, когда комментирование, как указано выше, я получаю:

range(len()):
8.231641875551514
enum():
9.974262515773656

Ответ 7

Я провел тест времени и обнаружил диапазон примерно в 2 раза быстрее, чем перечисление. (на python 3.6 для Win32)

лучше всего 3, для len (a) = 1M

  • перечисление (a): 0.125s
  • диапазон (len (a)): 0.058s

Надеюсь, что это поможет.

FYI: Я начал этот тест, чтобы сравнить скорость python vs vba... и выяснил, что vba на самом деле на 7 раз быстрее, чем метод диапазона... это из-за моих плохих навыков питона?

Конечно, python может сделать лучше, чем vba как-то

script для перечисления

import time
a = [0]
a = a * 1000000
time.perf_counter()

for i,j in enumerate(a):
    pass

print(time.perf_counter())

script для диапазона

import time
a = [0]
a = a * 1000000
time.perf_counter()

for i in range(len(a)):
    pass

print(time.perf_counter())

script для vba (0.008s)

Sub timetest_for()
Dim a(1000000) As Byte
Dim i As Long
tproc = Timer
For i = 1 To UBound(a)
Next i
Debug.Print Timer - tproc
End Sub

Ответ 8

Просто используйте range(). Если вы все равно будете использовать все индексы, xrange() не дает реальной выгоды (если только len(a) действительно большой). И enumerate() создает более богатую структуру данных, которую вы собираетесь немедленно выбросить.