具有多个 If-Break 条件的 For-Else 语句

For-Else Statement with Multiple If-Break Conditions

我写了一个简单的 python 模块 returns 给定 N 的质数,使用 bool 标志 is_prime 如下:

def generate_primes_up_to(M):
    n = 2
    primes = []    
    while n <= M:
        is_prime = True
        for p in primes:
            if p**2 > n: break
            if n % p == 0:
                is_prime = False
                break
        if is_prime: primes.append(n) 
        n += 1
    return primes

if __name__ == '__main__':
    generate_primes_up_to(100)

输出:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

现在,这实际上是使用 for-else 结构的理想情况,因为数字 n 只有在 for 中没有出现 break 时才是素数环形。因此,我将函数更改为:

def generate_primes_up_to(M, flag='nonumpy'):
    n = 2
    primes = []    
    while n <= M:
        for p in primes:
            if p**2 > n: break
            if n % p == 0: break
        else: primes.append(n) 
        n += 1
    return primes

但现在代码输出:

[2, 5, 27]

我不明白为什么 if p**2 > n: break 表达式会干扰 for-else 子句的流程。如果我删除该行,代码将再次产生正确的输出。

导致问题的条件是 -

if p**2 > n: break

举个例子 - 7 ,当我们检查 7 是否是质数时,我们已经发现 - [2,3,5] 是质数,上面的条件打破了 for 循环,当我们检查 33**2 = 9 时,它大于 7 .

删除那个条件,它工作正常(虽然它很慢)。

在原来的循环中(没有 for-else 结构),它起作用了,因为在那种情况下你刚刚跳出循环,你没有改变标志 is_prime .


使用 for..else 结构,else 部分仅在我们退出循环而不使用 break 语句时执行。

但是在上述情况下,我们使用了break语句,因此else部分没有被执行。

你也可以使用next:

def generate_primes_up_to(M):
    n = 2
    primes = []
    while n <= M:
        if next((False for p in primes if not n % p), True):
            primes.append(n)
        n += 1

    return primes