As we all know, Python is not a language with high execution efficiency. Also, looping is a very time-consuming operation in any language. If any simple single-step operation takes 1 unit of time, if this operation is repeated tens of thousands of times, the final time will increase by tens of thousands of times.
while
and for
are two commonly used keywords in Python to implement loops, and there is actually a gap in their running efficiency. For example the following test code:
import timeit
def while_loop(n=100_000_000):
i = 0
s = 0
while i < n:
s += i
i += 1
return s
def for_loop(n=100_000_000):
s = 0
for i in range(n):
s += i
return s
def main():
print('while loop\t\t', timeit.timeit(while_loop, number=1))
print('for loop\t\t', timeit.timeit(for_loop, number=1))
if __name__ == '__main__':
main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
This is a simple sum operation that computes the sum of all natural numbers from 1 to n. You can see that the for
loop is while
1.5 seconds faster.
The difference is mainly in the mechanism of the two.
In each loop, while
there are actually two for
more : bounds checking and i
incrementing of the variable . That is, each time the loop is executed, while will do a bounds check ( while i < n
) and an auto-increment calculation ( i +=1
). Both steps are explicit pure Python code.
for
Loops do not need to perform bounds checking and auto-increment operations, and no explicit Python code is added (pure Python code is less efficient than low-level C code). When the number of loops is large enough, there is a clear efficiency gap.
Two more functions could be added, adding unnecessary bounds checks and auto-increment calculations to the for
loop :
import timeit
def while_loop(n=100_000_000):
i = 0
s = 0
while i < n:
s += i
i += 1
return s
def for_loop(n=100_000_000):
s = 0
for i in range(n):
s += i
return s
def for_loop_with_inc(n=100_000_000):
s = 0
for i in range(n):
s += i
i += 1
return s
def for_loop_with_test(n=100_000_000):
s = 0
for i in range(n):
if i < n:
pass
s += i
return s
def main():
print('while loop\t\t', timeit.timeit(while_loop, number=1))
print('for loop\t\t', timeit.timeit(for_loop, number=1))
print('for loop with increment\t\t',
timeit.timeit(for_loop_with_inc, number=1))
print('for loop with test\t\t', timeit.timeit(for_loop_with_test, number=1))
if __name__ == '__main__':
main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => for loop with increment 4.602369500091299
# => for loop with test 4.18337869993411
It can be seen that the increased bounds checking and auto-increment operations do greatly affect the execution efficiency of the for
loop .
As mentioned earlier, Python's underlying interpreter and built-in functions are implemented in C language. The execution efficiency of C language is much greater than that of Python.
For the above operation of calculating the sum of arithmetic progressions, with the help of Python's built-in sum
function , the execution efficiency of the loopfor
can be much greater than or .while
import timeit
def while_loop(n=100_000_000):
i = 0
s = 0
while i < n:
s += i
i += 1
return s
def for_loop(n=100_000_000):
s = 0
for i in range(n):
s += i
return s
def sum_range(n=100_000_000):
return sum(range(n))
def main():
print('while loop\t\t', timeit.timeit(while_loop, number=1))
print('for loop\t\t', timeit.timeit(for_loop, number=1))
print('sum range\t\t', timeit.timeit(sum_range, number=1))
if __name__ == '__main__':
main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range 0.8658821999561042
It can be seen that after using the built-in function sum
to replace the loop, the execution efficiency of the code has been doubled.
sum
The accumulation operation of the built-in function is actually a kind of loop, but it is implemented in C language, and for
the summation operation in the loop is s += i
implemented . C > Python.
Expand your thinking. As a child, I have heard stories of childhood Gauss ingeniously calculating the sum of 1 to 100. The sum of 1…100 is (1 + 100) * 50. This calculation method can also be applied to the above summation operation.
import timeit
def while_loop(n=100_000_000):
i = 0
s = 0
while i < n:
s += i
i += 1
return s
def for_loop(n=100_000_000):
s = 0
for i in range(n):
s += i
return s
def sum_range(n=100_000_000):
return sum(range(n))
def math_sum(n=100_000_000):
return (n * (n - 1)) // 2
def main():
print('while loop\t\t', timeit.timeit(while_loop, number=1))
print('for loop\t\t', timeit.timeit(for_loop, number=1))
print('sum range\t\t', timeit.timeit(sum_range, number=1))
print('math sum\t\t', timeit.timeit(math_sum, number=1))
if __name__ == '__main__':
main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range 0.8658821999561042
# => math sum 2.400018274784088e-06
The execution time of the final math sum is about 2.4e-6
1 million times shorter. The idea here is that since the efficiency of the loop is low, a piece of code needs to be repeated hundreds of millions of times.
Simply don't loop, and use mathematical formulas to turn hundreds of millions of loop operations into only one step. Efficiency has naturally been unprecedentedly enhanced.
Final conclusion (a bit of a riddle person):
The fastest way to implement a loop --
--
-- is without a loop
For Python, use built-in functions wherever possible, keeping pure Python code in loops to a minimum.
References