2016-09-21 4 views
-2

У меня есть этот код:Обратный список при создании

def iterate_through_list_1(arr): 
    lala = None 
    for i in range(len(arr))[::-1]: 
     lala = i 

def iterate_through_list_2(arr): 
    lala = None 
    for i in range(len(arr), 0, -1): 
     lala = i 

Логически, перебирая список, созданный range() в обратном порядке должно быть более эффективным, чем создание списка с range() и реверсирования его потом с [::-1]. Но cProfile говорит мне, что функция iterate_through_list_1 работает быстрее.

Я использовал python-3. И здесь вы можете увидеть результат профилирования на двух идентичных массивах с 100000000 элементами в них.

ncalls tottime percall cumtime percall filename:lineno(function) 
    1 5.029 5.029 5.029 5.029 bs.py:24(iterate_throgh_list_2) 
    1 4.842 4.842 4.842 4.842 bs.py:19(iterate_throgh_list_1) 

Что произошло под кусочками Python при создании списка?

+3

Python 2.x или 3.x? Каковы цифры, какая разница во времени? Как вы его протестировали? Вы использовали несколько итераций? –

+0

Вторая функция * много * более очевидна. Предпочитайте это, если нет * массивного * преимущества - и это имеет значение для вашего приложения. –

+0

@MartinBonner, если это прекрасно, что относительно 'для obj в обратном (arr)'? Или, если вам действительно нужны указатели, 'для idx, obj в перечислении (reverse (arr))'? –

ответ

1

Хорошо спроектированный тест показывает, что первая функция является самой медленной на Python 2.x (главным образом потому, что должны быть созданы два списка, сначала один как увеличивающийся диапазон, второй - как первый). Я также включил демо-версию, используя reversed.

from __future__ import print_function 
import sys 
import timeit 

def iterate_through_list_1(arr): 
    lala = None 
    for i in range(len(arr))[::-1]: 
     lala = i 

def iterate_through_list_2(arr): 
    lala = None 
    for i in range(len(arr), 0, -1): 
     lala = i 

def correct_iterate_reversed(arr): 
    lala = None 
    for obj in reversed(arr): 
     lala = obj 


print(sys.version) 
print('iterate_through_list_1', timeit.timeit('iterate_through_list_1(seq)', 
               setup='from __main__ import iterate_through_list_1\nseq = range(0, 10000)', 
               number=10000)) 
print('iterate_through_list_2', timeit.timeit('iterate_through_list_2(seq)', 
               setup='from __main__ import iterate_through_list_2\nseq = range(0, 10000)', 
               number=10000)) 
print('correct_iterate_reversed', timeit.timeit('correct_iterate_reversed(seq)', 
               setup='from __main__ import correct_iterate_reversed\nseq = range(0, 10000)', 
               number=10000)) 

Результаты:

2.7.12 (default, Jun 29 2016, 14:05:02) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] 
iterate_through_list_1 3.87919592857 
iterate_through_list_2 3.38339591026 
correct_iterate_reversed 2.78083491325 

Различия в 3.х все пренебрежимо, поскольку в каждом случае объекты итерации ленивы.

3.5.2 (default, Jul 28 2016, 21:28:00) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] 
iterate_through_list_1 2.986786328998278 
iterate_through_list_2 2.9836046030031866 
correct_iterate_reversed 2.9411962590020266 
Смежные вопросы