![](/img/trans.png)
[英]Why is looping over range() in Python faster than using a while loop?
[英]Why is while loop much faster than range in this case?
根據這篇文章 ,范圍循環應該比python中的while循環更快,但請看下面的代碼。 它僅用於測試數字是否為素數,如果n不是素數則返回除數。
import time
def isPrimeWhile(n):
i = 2
while(i <= n/2+1):
if(n%i == 0):
return i
i += 1
return n
def isPrimeRange(n):
for i in range(2,n/2+1):
if(n%i == 0):
return i
return n
n = 353591872901
start = time.time()
isPrimeWhile(n)
print("%s while seconds"%(time.time() - start))
start = time.time()
isPrimeRange(n)
print("%s range seconds"%(time.time() - start))
運行代碼,你會發現while循環比range循環快得多。我猜測范圍(0,aLargeNumber)需要很長時間才能運行。 但為什么在上面提到的上一篇文章中,范圍方法要快得多? 任何答案?
由於您使用的是Python 2+(您的代碼需要使用整數除法在Python 3+中工作),因此您會遇到Python 2+ range
生成所有元素的列表然后迭代它們的事實。
這可以解釋while
和range
函數運行所需的時間差異。
在Python 3+的代碼中,需要進行以下更改:
def isPrimeRange(n):
for i in range(2,n//2+1): # integer division
if(n%i == 0):
return i
return n
這篇Python博客文章詳細解釋了Python 2+中range
(返回列表)和xrange
(返回迭代器)之間的區別以及Python 3+如何更改此功能。
從這個來源中選出最相關的段落是:
當您使用迭代器時,for語句的每個循環都會動態生成下一個數字。 原始range()函數在for循環開始執行之前立即生成所有數字。 原始range()函數的問題在於它在生成大量數字時使用了大量內存。 但是,只需少量數字就可以更快。 請注意,在Python 3.x中,您仍然可以通過將返回的生成器傳遞給list()函數來生成列表。
正如其他人所提到的,主要問題似乎是在Python 2.7中使用range
而不是range
。 使用%timeit
,如果使用xrange
(Python 2.7),這兩個函數幾乎相同。
%timeit isPrimeRange(n)
100000 loops, best of 3: 15.2 µs per loop
%timeit isPrimeWhile(n)
100000 loops, best of 3: 15.8 µs per loop
%load_ext line_profiler
%load_ext memory_profiler
from isPrimeRange import isPrimeRange
from isPrimeWhile import isPrimeWhile
n = 353591872901
isPrimeRange:Line Profiler
%lprun -f isPrimeRange isPrimeRange(n)
Timer unit: 1e-06 s
**Total time: 5.5e-05 s**
File: isPrimeRange.py
Function: isPrimeRange at line 1
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 def isPrimeRange(n):
2 82 25 0.3 45.5 for i in xrange(2,n/2+1):
3 82 29 0.4 52.7 if(n%i == 0):
4 1 1 1.0 1.8 return i
5 return n
isPrimeWhile:Line Profiler
%lprun -f isPrimeWhile isPrimeWhile(n)
Timer unit: 1e-06 s
**Total time: 9e-05 s**
File: isPrimeWhile.py
Function: isPrimeWhile at line 3
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 def isPrimeWhile(n):
4 1 1 1.0 1.1 i = 2
5 82 34 0.4 37.8 while(i <= n/2+1):
6 82 31 0.4 34.4 if(n%i == 0):
7 1 0 0.0 0.0 return i
8 81 24 0.3 26.7 i += 1
9 return n
使用iPython的內存分析器,您可以看到兩者都使用相同數量的內存。
isPrimeRange:Memory Profiler
%mprun -f isPrimeRange isPrimeRange(n)
('',)
Filename: isPrimeRange.py
Line # Mem usage Increment Line Contents
================================================
1 24.2 MiB 0.0 MiB def isPrimeRange(n):
2 24.2 MiB 0.0 MiB for i in xrange(2,n/2+1):
3 24.2 MiB 0.0 MiB if(n%i == 0):
4 24.2 MiB 0.0 MiB return i
5 return n
isPrimeWhile:Memory Profiler
%mprun -f isPrimeWhile isPrimeWhile(n)
('',)
Filename: isPrimeWhile.py
Line # Mem usage Increment Line Contents
================================================
3 24.2 MiB 0.0 MiB def isPrimeWhile(n):
4 24.2 MiB 0.0 MiB i = 2
5 24.2 MiB 0.0 MiB while(i <= n/2+1):
6 24.2 MiB 0.0 MiB if(n%i == 0):
7 24.2 MiB 0.0 MiB return i
8 24.2 MiB 0.0 MiB i += 1
9 return n
你也可以嘗試使用
import time
def isPrimeWhile(n):
i = 2
while(i <= n/2+1):
if(n%i == 0):
return i
i += 1
return n
def isPrimeRange(n):
for i in xrange(2,n/2+1):
if(n%i == 0):
return i
return n
n = 353591872901
start = time.time()
isPrimeWhile(n)
print("%s while seconds"%(time.time() - start))
start = time.time()
isPrimeRange(n)
print("%s while seconds"%(time.time() - start))
1.28746032715e-05秒
6.91413879395e-06秒
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.