Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is looping over range() in Python faster than using a while loop?

The other day I was doing some Python benchmarking and I came across something interesting. Below are two loops that do more or less the same thing. Loop 1 takes about twice as long as loop 2 to execute.

Loop 1:

int i = 0 while i < 100000000:   i += 1 

Loop 2:

for n in range(0,100000000):   pass 

Why is the first loop so much slower? I know it's a trivial example but it's piqued my interest. Is there something special about the range() function that makes it more efficient than incrementing a variable the same way?

like image 569
A. Dorton Avatar asked May 15 '09 15:05

A. Dorton


People also ask

WHY IS for loop faster than while loop in Python?

While loop cannot be iterated on Generators directly. For loop with range() uses 3 operations. range() function is implemented in C, so, its faster. On basis of disassembly, for loop is faster than while loop.

Which loop is faster Python?

In this case, the for loop is faster, but also more elegant compared to while. Please, have in mind that you can't apply list comprehensions in all cases when you need loops. Some more complex situations require the ordinary for or even while loops.

Why for loop is faster than while loop?

Using for: % Time elapsed: 0.0010001659 seconds. Using while: % Time elapsed: 0.026000023 seconds. The main reason that While is much slower is because the while loop checks the condition after each iteration, so if you are going to write this code, just use a for loop instead.

What is difference between Range function in for loop and while loop?

Yes, there is a huge difference between while and for. The for statement iterates through a collection or iterable object or generator function. The while statement simply loops until a condition is False. It isn't preference.


2 Answers

see the disassembly of python byte code, you may get a more concrete idea

use while loop:

1           0 LOAD_CONST               0 (0)             3 STORE_NAME               0 (i)  2           6 SETUP_LOOP              28 (to 37)       >>    9 LOAD_NAME                0 (i)              # <-            12 LOAD_CONST               1 (100000000)      # <-            15 COMPARE_OP               0 (<)              # <-            18 JUMP_IF_FALSE           14 (to 35)          # <-            21 POP_TOP                                     # <-  3          22 LOAD_NAME                0 (i)              # <-            25 LOAD_CONST               2 (1)              # <-            28 INPLACE_ADD                                 # <-            29 STORE_NAME               0 (i)              # <-            32 JUMP_ABSOLUTE            9                  # <-       >>   35 POP_TOP            36 POP_BLOCK 

The loop body has 10 op

use range:

1           0 SETUP_LOOP              23 (to 26)             3 LOAD_NAME                0 (range)             6 LOAD_CONST               0 (0)             9 LOAD_CONST               1 (100000000)            12 CALL_FUNCTION            2            15 GET_ITER       >>   16 FOR_ITER                 6 (to 25)        # <-            19 STORE_NAME               1 (n)            # <-  2          22 JUMP_ABSOLUTE           16                # <-       >>   25 POP_BLOCK       >>   26 LOAD_CONST               2 (None)            29 RETURN_VALUE 

The loop body has 3 op

The time to run C code is much shorter than intepretor and can be ignored.

like image 194
kcwu Avatar answered Oct 11 '22 00:10

kcwu


range() is implemented in C, whereas i += 1 is interpreted.

Using xrange() could make it even faster for large numbers. Starting with Python 3.0 range() is the same as previously xrange().

like image 45
Georg Schölly Avatar answered Oct 10 '22 22:10

Georg Schölly