2014-11-14 2 views
0

В python, который быстрее?Python для каждого быстрее, чем для индексирования?

for word in listOfWords: 
    doSomethingToWord(word) 
for i in range(len(listOfWords)): 
    doSomethingToWord(listOfWords[i]) 

Конечно, я хотел бы использовать xrange в питона 2.x.

Мое предположение - 1. быстрее, чем 2. Если да, то почему?

+0

Вы можете проверить его сами;). И да 1 быстрее. –

+0

Для 2, для каждого i вы можете рассчитать длину списка. Сначала быстрее –

+1

Ваше предположение, скорее всего, верно по причинам, которые вы, вероятно, догадались, - он может оптимизировать поиск элементов в коде C.В обоих случаях вы вызываете 'next' на собственный объект, так что это должно быть довольно быстро в любом случае (хотя xrange все равно может потребоваться больше вычислений для обработки начала, остановки и шага и т. Д.) ... но в последнем случае случае, вам необходимо выполнить дополнительный шаг _indexing_ объекта, который вам не нужно было делать раньше. – mgilson

ответ

3

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

from datetime import datetime 
arr = [4 for _ in xrange(10**8)] 

startTime = datetime.now() 
for i in arr: 
    i 
print datetime.now() - startTime 

startTime = datetime.now() 
for i in xrange(len(arr)): 
    arr[i] 
print datetime.now() - startTime 

На моей машине это:

0:00:04.822513 
0:00:05.676396 

Обратите внимание, что список вы перебор должен быть довольно большим, чтобы увидеть разницу. Второй цикл длиннее, потому что каждый раз вам нужно просмотреть индекс (arr[i]), а также сгенерировать значения для xrange.

Пожалуйста, не тратьте слишком много времени в основном бесполезной микрооптимизации, скорее попробуйте посмотреть, можете ли вы улучшить вычислительную сложность ваших внутренних функций цикла.

+1

Использование 'timeit' было бы лучше – glglgl

+1

@glglgl, много было бы лучше. Например, говоря, что такой тест не имеет смысла, потому что многие другие вещи важнее, чем микрооптимизация. Работает ли datetime? Да. Означает ли это, что ОП задает? Да. я объясню почему? Да. Я говорю, что делать лучше? Да. Поэтому ответ достаточно хорош. –

+1

Хотя время может быть лучше, я выбираю этот ответ как правильный, потому что он объяснил, почему в ответе. Никто другой не сделал. (хотя кто-то сделал в комментарии к моему вопросу) – CamHart

4

модуль timeit Используйте Python, чтобы ответить на этот вопрос такой:

[email protected]:~$ python -m timeit -s "listOfWords=['hello']*1000" "for word in listOfWords: len(word)" 
10000 loops, best of 3: 37.2 usec per loop 
[email protected]:~$ python -m timeit -s "listOfWords=['hello']*1000" "for i in range(len(listOfWords)): len(listOfWords[i])" 
10000 loops, best of 3: 52.1 usec per loop 
2

просто попробуйте timeit.

In [2]: def solve(listOfWords): 
     for word in range(len(listOfWords)): 
       pass 
    ...:  

In [3]: %timeit solve(xrange(10**5)) 
100 loops, best of 3: 4.34 ms per loop 

In [4]: def solve(listOfWords): 
     for word in listOfWords: 
       pass 
    ...:  

In [5]: %timeit solve(xrange(10**5)) 
1000 loops, best of 3: 1.84 ms per loop 
1

В дополнении к преимуществу скорости, 1 является «чище выглядящим», но и будет работать для последовательностей, которые не поддерживают Len, а именно выражение генератора и результаты функций генератора. Чтобы использовать решение 2, вам сначала нужно будет преобразовать генератор в список, чтобы получить его длину , если бы вы могли. Но что, если генератор генерирует список всех простых чисел, а doSomething ищет первое значение> 100?

for num in prime_number_generator(): 
    if num > 100: return num 

Невозможно преобразовать это во вторую форму, поскольку этот генератор не имеет конца.

Кроме того, что, если очень дорого создавать элементы списка (как при извлечении из базы данных или удаленного веб-сервера)? Если вы ищете подходящее значение из сгенерированного набора значений N, с # 1 вы можете выйти, как только найдете совпадение, и избегать в среднем генерации значений N/2. Чтобы использовать # 2, сначала нужно сгенерировать все значения N, чтобы получить длину, чтобы сделать диапазон.

Существует причина, по которой Python 3 преобразовал многие встроенные функции, чтобы возвращать итераторы вместо списков - они более гибкие.

What is Pythonic? 
"for i in range(len(seq)):"? No. 
Use "for x in seq:" 
Смежные вопросы