Ответ 1
for item in list:
это, очевидно, тот, с меньшим количеством вызовов функций.
Если вы хотите получить индекс предметов по ходу дела, используйте перечисление, как это
for pos, item in enumerate(collection):
Скажем, у меня есть список элементов:
x = [1, 2, 3, 4, 5]
Мне нужно выполнить некоторые функции для каждого из этих элементов. В определенном случае мне нужно вернуть индекс элемента.
Каков наилучший и эффективный способ?
for item in list:
....
или
for i in range(len(list)):
....
for item in list:
это, очевидно, тот, с меньшим количеством вызовов функций.
Если вы хотите получить индекс предметов по ходу дела, используйте перечисление, как это
for pos, item in enumerate(collection):
def loop_1(data):
for i in range(len(data)):
print(data[i])
def looper_2(data):
for val in data:
print(val)
Проверка с помощью dis дает нам следующий байт-код для loop_1:
12 0 SETUP_LOOP 40 (to 43)
3 LOAD_GLOBAL 0 (range)
6 LOAD_GLOBAL 1 (len)
9 LOAD_FAST 0 (data)
12 CALL_FUNCTION 1
15 CALL_FUNCTION 1
18 GET_ITER
>> 19 FOR_ITER 20 (to 42)
22 STORE_FAST 1 (i)
13 25 LOAD_GLOBAL 2 (print)
28 LOAD_FAST 0 (data)
31 LOAD_FAST 1 (i)
34 BINARY_SUBSCR
35 CALL_FUNCTION 1
38 POP_TOP
39 JUMP_ABSOLUTE 19
>> 42 POP_BLOCK
>> 43 LOAD_CONST 0 (None)
46 RETURN_VALUE
Байт-код для loop_2 выглядит так:
17 0 SETUP_LOOP 24 (to 27)
3 LOAD_FAST 0 (data)
6 GET_ITER
>> 7 FOR_ITER 16 (to 26)
10 STORE_FAST 1 (val)
18 13 LOAD_GLOBAL 0 (print)
16 LOAD_FAST 1 (val)
19 CALL_FUNCTION 1
22 POP_TOP
23 JUMP_ABSOLUTE 7
>> 26 POP_BLOCK
>> 27 LOAD_CONST 0 (None)
30 RETURN_VALUE
Вторая версия, очевидно, лучше.
Другим возможным решением было бы использовать numpy
, который был бы очень эффективным, поскольку большие списки, возможно, были бы более эффективными, чем понимание списка или цикл for.
import numpy as np
a = np.arange(5.0) # a --> array([0., 1., 2., 3., 4.])
# numpy operates on arrays element by element
#
b =3.*a # b --> array([0., 3., 6., 9., 12.])
Это довольно простая операция, но вы можете усложниться, используя массив как просто аргумент в формуле. Для больших массивов это может быть намного быстрее, чем понимание списка, и делает код более понятным и понятным для чтения (нет необходимости создавать функцию для сопоставления в понимании списка). Вы также можете использовать индексирование и нарезку, чтобы настроить то, что вы хотите сделать:
Если вы хотите иметь доступ к фактическим позициям индекса, используйте ndenumerate
# b is as above
for i, x in np.ndenumerate(b):
print i, x
Выход этого цикла for:
(0,) 0.0
(1,) 3.0
(2,) 6.0
(3,) 9.0
(4,) 12.0
ПРИМЕЧАНИЕ. Индекс возвращается как кортеж numpy для обработки дополнительных измерений. Здесь мы имеем только одно измерение, поэтому вам нужно будет распаковать кортеж, чтобы получить индекс элемента.
Очевидно, что for i in range(len(list)):
будет медленнее - в Python 2 это эквивалентно следующему:
list2 = range(len(list))
for i in list2:
...
Если бы это было быстрее, то это было бы еще быстрее, верно?
list2 = range(len(list))
list3 = range(len(list2))
list4 = range(len(list3))
for i in list4:
...