简体   繁体   中英

Python infinite loop with for else

I am writing a function to count primes. I try to use a for-break-else framework nested in a while loop. However, I got an infinite loop. I knew the else is not with the right indentation. After I moved else ahead and made it paralleled with for, the problem was solved. However, I feel difficult to understand why the else block's original place would give me the infinite loop. Can someone help me with that? Thanks.

def count_primes(num):
    primes = [2]
    x = 3
    if num < 2:
        return 0
    else:
        while x <= num:
            for y in range(3,x,2):
                if x%y ==0:
                    x += 2
                    break #jump out the for loop
                else:
                    primes.append(x)
                    x +=2 
    return primes
                    

In your function, you initialised your variable x at 3 but in your for loop you defined your loop range to go from y = 3 to x = 3. You should remember that the range function range(a,b) goes from a to (b-1) . Thus your loop is trying to loop over 3 to 2, which is not possible, thus you never execute the code within. That is why you have an infinite loop, because it always tries to run the loop, then cannot, then goes back to the while loop, without incrementing x.

For the purpose of your code I would then initialize x at 5 for the loop to be executed:

def count_primes(num):
    primes = [2]
    x = 5
    if num < 2:
        return 0
    else:
        while x <= num:
            for y in range(3, x, 2):
                if x % y == 0:
                    x += 2
                    break  # jump out the for loop
                else:
                    primes.append(x)
                    x += 2
    return primes

But after testing, it is clear your code wouldn't give you a correct answer though. Testing your function with num = 100 gives the result below, which is incorrect (21 for example is not a prime number):

>>> count_primes(100)
[2, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129]

To keep with the logic you are trying to implement, here is another solution to return the list or primes:

def count_primes(num):
    if num <= 1:
        return []

    primes = [2]
    x = 3
    while x <= num:
        is_prime = True
        for prime_numbers in primes:
            if x % prime_numbers == 0:
                is_prime = False
                break
        if is_prime:
            primes.append(x)
        x += 2
    return primes

Testing it with num = 100 gives us the correct list of prime numbers below 100:

>>> count_primes(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]

Python uses indentation to indicate a block of code. When else is with if, it gets fired everytime if is wrong. This increments value of x by x+=2. This increases the range of the loop everytime if statement is false, thus resulting in infinite loop. When else is paralled with for the x+=2 statement gets executed only when the for loop condition is false.

else:
primes.append(x)
x +=2 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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