Требуется только индекс: перечислять или (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()
создает более богатую структуру данных, которую вы собираетесь немедленно выбросить.