2009-08-29 3 views
4

Почему «перечислять» медленнее, чем «xrange + lst [i]»?Почему Python перечислил так медленно?

 

>>> from timeit import Timer 
>>> lst = [1,2,3,0,1,2]*1000 
>>> setup = 'from __main__ import lst' 
>>> s1 = """ 
for i in range(len(lst)): 
    elem = lst[i] 
""" 
>>> s2 = """ 
for i in xrange(len(lst)): 
    elem = lst[i] 
""" 
>>> s3 = """ 
for i, v in enumerate(lst): 
    elem = v 
""" 
>>> t1 = Timer(s1, setup); t2 = Timer(s2, setup); t3 = Timer(s3, setup) 
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000) 
(1.9263118636586494, 1.6119261665937992, 1.9606022553145719) 
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000) 
(1.93520258859715, 1.6145745478824836, 1.9529405971988041) 
 

EDIT: я иметь в виду, почему

for i, v in enumerate(lst): 
    elem = i, v 
медленнее, чем
for i in xrange(len(lst)): 
    elem = i, lst[i] 

ответ

14

Если вы измеряете правильно, вы увидите, что нет по существу никакой разницы (перечислить микроскопически быстрее, чем xrange в этом примере, но хорошо в пределах шума):

$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i in xrange(len(lst)): elem=lst[i]' 
1000 loops, best of 3: 480 usec per loop 
$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i, elem in enumerate(lst): pass' 
1000 loops, best of 3: 473 usec per loop 

(Кстати, я всегда рекомендую использовать timeit на shell, как это, не в коде или в приглашении интерпретатора, как вы это делаете, только потому, что вывод так красиво отформатирован и применим, с единицами измерения времени и всего).

В коде, у вас есть дополнительное задание в случае перечисления, вы назначьте элемент списка V в пункте в for заголовка, а затем снова назначить v к elem; в то время как в случае xrange вы назначаете элемент только один раз, elem. В моем случае я также назначаю только один раз в любом случае, конечно; почему бы вы ХОТИТЕ назначить несколько раз? Что бы вы ни делали с elem и i в теле цикла, вы можете сделать это одинаково в двух формах, которые я измеряю, просто без избыточности, которую имеет ваш список перечислений.

5

Возможно потому, что вы ковылял enumerate. Попробуйте это:

>>> s3 = """ 
for i, elem in enumerate(lst): 
    pass 
""" 

Обновление Две дополнительные причины для использования timeit в командной строке, что Алекс не упомянул:

(1) Это делает «лучший из N» для вас.
(2) Это поможет вам, сколько итераций необходимо для получения значимого результата.

+2

Если непонятно, почему ответ Джона имеет смысл, результат, полученный путем перечисления, уже содержит элемент списка поиска. Используя это имя в переменных for-loop, вы сделаете это понятным. в вашей первоначальной версии вы дважды выполнили поиск! – SingleNegationElimination

+3

@TokenMacGuy и 2 комментария: «уже содержит элемент списка поиска ... вы дважды выполнили поиск»: это неверно; элемент извлекается из списка только ONCE; разница между этими двумя версиями является избыточным назначением формы 'x = y', которая не требует« поиска ». –

Смежные вопросы