我正在研究Eratosthenes的Sieve,我正在分析如何从候选人范围中过滤非素数。
为了测试,我使用了这个命令:
import timeit
print timeit.timeit(stmt="sieve(1000)", setup='from sieve import sieve', number=1000)
这就是我目前所拥有的:
def sieve(limit):
primes = [2]
pRange = range(3, limit, 2)
while pRange:
p = pRange.pop(0)
filter_range = range(p**2, limit, p << 1)
pRange = filter(lambda x: x not in filter_range, pRange)
primes.append(p)
return primes
Seconds =&gt; 5.42698788643
然后我想如果我要从范围中弹出第一个元素,我可能想这样写:
def sieve(limit):
primes = [2]
pRange = range(3, limit, 2)
for p in pRange:
filter_range = range(p**2, limit, p << 1)
pRange = filter(lambda x: x not in filter_range, pRange)
primes.append(p)
return primes
但事实证明15.7085180283
秒后速度要慢得多。
为什么会这样? for循环是否迭代了pRange的初始值并且没有更新?
答案 0 :(得分:3)
for p in pRange:
这会评估pRange
,将其转换为列表(Python 2)或生成器(Python 3),然后遍历范围中的项目。 不会重新评估pRange
。
无论哪种方式都会导致比while
循环更多的循环迭代,因为后者每次循环都会重新评估范围。
请记住,在Python中,变量是所有引用。即使a = 5
之类的意思是“设置a
来引用值为5
的整数常量。”同样,pRange = filter(...)
表示“获取filter(...)
返回的对象,并设置pRange
以引用它。释放对用于引用的任何值pRange
的引用(可能垃圾收集它以后如果没有引用它。)“