简体   繁体   English

为什么while循环比for循环更有效?

[英]Why is a while loop much more efficient than a for loop here?

I'm working on the Sieve of Eratosthenes and I'm analyzing how I could filter non-prime numbers from the range of candidates. 我正在研究Eratosthenes筛,并且正在分析如何从候选范围中过滤非素数。

For testing, I'm using this command: 为了进行测试,我使用以下命令:

import timeit
print timeit.timeit(stmt="sieve(1000)", setup='from sieve import sieve', number=1000)

This is what I currently have: 这是我目前拥有的:

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 => 5.42698788643 秒=> 5.42698788643

I then thought that if I was going to pop the first element from range, I might want to write it like this: 然后,我以为如果要弹出范围中的第一个元素,我可能要这样写:

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

but it turns out to be much slower at 15.7085180283 Seconds. 但事实证明,速度要慢得多,为15.7085180283秒。

Why is this happening? 为什么会这样呢? Is the for loop iterating over the initial value of pRange and isn't updating? for循环是否在pRange的初始值上迭代并且没有更新?

for p in pRange:

This evaluates pRange , turning it into a list (Python 2) or a generator (Python 3), and then iterates through the items in the range. 这将评估pRange ,将其转换为列表(Python 2)或生成器(Python 3),然后遍历范围内的项目。 It does not re-evaluate pRange . 它不会重新评估pRange

Either way will result in more loop iterations than the while loop would, because the latter is re-evaluating the range each time through the loop. 两种方式都会导致比while循环更多的循环迭代,因为while循环每次都会通过循环重新评估范围。

Remember, in Python, variables are all references. 请记住,在Python中,变量都是引用。 Even something like a = 5 means "set a to refer to an integer constant with the value 5 ." 甚至a = 5意思也意味着“将a设置为引用值为5的整数常量”。 Likewise, pRange = filter(...) means "take the object that filter(...) returned, and set pRange to refer to it. Release the reference to whatever value pRange used to refer to (and possibly garbage collect it later if nothing refers to it)." 同样, pRange = filter(...)意思是“获取filter(...)返回的对象,并将pRange设置为pRange进行引用。释放对pRange所引用的任何值的引用(并可能在以后进行垃圾回收)如果没有其他说明)。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM