Reverse the list while creation
Question: I have this code:

    
    
    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
    

Logically, iterating through list created by `range()` in reverse order should
be more efficient, than creating list with `range()` and reversing it
afterwards with `[::-1]`. But _cProfile_ tells me, that
`iterate_through_list_1` function works faster.

I used python-3. And here you can see output of profiling on the two identical
arrays with 100000000 elements in them.

    
    
    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)
    

What happened underneath Python slices while list creation?


Answer: Well designed test shows that first function is slowest on Python 2.x (mostly
because two lists have to be created, first one as a increasing range, second
one as a reverted first one). I also included a demo using `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))
    

Results:

    
    
    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
    

Differences in 3.x are all neglible, because in each case objects iterated
over are lazy.

    
    
    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
    

