6. is_prime and for loops with else


#1

I want to understand the difference between having the else statement inside just the for loop vs inside the if within my for loop (last else indented twice instead of once).

Here is my code that fails at is_prime(9).

def is_prime(x):
    if x<=1:
        return False
    elif x<=3:
        return True
    else:
        for n in range(2,x):
            if x%n==0:
                return False
                break
            else:
                return True

Whereas this code passes:

def is_prime(x):
        if x<=1:
            return False
        elif x<=3:
            return True
        else:
            for n in range(2,x):
                if x%n==0:
                    return False
                    break
            else:
                return True

Can someone help me understand why the code with else applied to the for loop instead of within the if in the for loop fails at 9 specifically, rather than 8 or some other number that is not prime?

Thanks!


#2

@gwatts229: Having an else statement inside a loop instructions will cause the program to execute the instructions inside of it (else), inside your loop which means it could be executed several times, if and only if the condition in the if statement is false.
While outside of your loop, it will execute once, considering there's no recursive calling nor other loops.

Other than that you're using the reserved word return which forces the program to stop and go back to where it was called on your program.

Why it fails? Because, considering x = 9, the first time it loops through the range 2 until 8 it will ask:

for fromSomething in somethingElse:
    if 9 % 2 == 0: #Evaluates as False
      return False
      break #This is not needed since the return will force the program to stop the execution and go back to where the function was called
    else:#Would be executed several times in case the if statement was False and there was no such return
      return True #If it falls here, it would mean the number is prime but isn't in the case x = 9

Having the else outside of your for loop guarantees that in case the tests inside your loop are always false, and such won't execute the return False, whenever it leaves the loop it will execute the else and return True ***

Hope I was clear, if not, let me know and I'll try to explain in a different way!

***I'm considering the example given by you with the return statements, don't consider it as being general for all cases.


#3

Thanks for the detailed explanation g4be. I now understand how these execute differently, but I'm trying to understand why this failed at 9 specifically (why not 8 or 4, for example)?

Here's my thinking: the 2nd block of code that fails should fail earlier than 9 - let's take is_prime(8) as an example:

for n in range(2,8):

iteration 1: if 8%2==0: #this is True, so return False, go to next iteration
iteration 2: if 8%3==0: #this is False, so go to the else of if/else within for and return True

Unless Codeacademy is checking random numbers (I'd assume it iterates through a range of int's low to high) shouldn't I have seen the incorrect code fail earlier than is_prime(9)? That is my main question...

Thanks in advance!


#4

@gwatts229: In fact your code doesn't fail for 8, 4 or any other multiple of 2.
It stops at the first time it iterates so it will return False, since it's not a prime number, and go back to where your function is_prime() was called in your code.

Edit: some more info about the return statement:

The above text can be found in the following link: Python Functions

Let me know if there's something unclear :slight_smile:


#5

I think I finally understand:

Each iteration up until is_prime(9):

is_prime(1), is_prime(2), is_prime(2) are explicitly handled

4%2==0 #is True so return False, 4 is not prime, therefore correct
5%2==0 #is False so return True, 5 is prime, therefore correct
6%2==0 #is True so return False, 6 is not prime, therefore correct
7%2==0 #is False so return True, 7 is prime, therefore correct
8%2==0 #is True so return False, 8 is not prime, therefore correct
9%2==0 #is False so return True, 9 is NOT prime, therefore incorrect

The fact that my loop only ran once is exactly why the first failure happens to be at is_prime(9).

Am I understanding that correctly? Thanks for all of the help!


#6

@gwatts229: Each time you iterate, you iterable, n, will get a different value from the 2 to x-1 so each time you'll be comparing x % n == 0.
But if X % N, considering N to be in the range mentioned above, is equal to zero, the condition will be True, the program will execute the instructions within the brackets, which are return True and break (there's no need to use break in this case tho), and will return, will simply ignore all the rest and go back to where the function, is_prime(), was called.

I'd suggest to give it a check on the link I've posted, it might help you but you're getting there!


#7

Right, so am I correct in saying my incorrect code is only ever checking for x%2==0 and ignoring all of the other iterations of n to (x-1)? for x = 3 and up?

I also corrected my examples loops above, and here they are in the correct form:

4%2==0 #is True so return False, 4 is not prime, therefore correct
5%2==0 #is False so return True, 5 is prime, therefore correct
6%2==0 #is True so return False, 6 is not prime, therefore correct
7%2==0 #is False so return True, 7 is prime, therefore correct
8%2==0 #is True so return False, 8 is not prime, therefore correct
9%2==0 #is False so return True, 9 is NOT prime, therefore incorrect


#8

If the entry is 2 (two), it won't really execute, as far as I know though.
And actually, the value of x is fixed while the value of n will continue to change each iteration so it would be something like this:

x = 9
for n in range(2,x):
    if x % n == 0:
      #Do something
#Continues the code
#First time: 9 % 2  == 0 ? False
#Second time: 9 % 3 == 0? True, so it will execute the commands within the if statement

Hope it's clear now, if not, let me know :slight_smile: