Transforming for loops into while loops

Note that it's always possible to transform for-loops into while loops:

Consider the following:

for i in range(N):
    print(i)

This is the same as

i = 0
while i < N:
    print(i)
    i += 1

Note that a for-loop is preferable here -- there is much less room for error.

Break

break stops the execution of a loop. Here is an example:

In [1]:
def is_prime(n):
    '''Return True iff n is prime
    Arguments:
    n -- a  non-negative integer
    '''
    if n <= 1:
        return False
    
    for i in range(2, n):  
        if n % i == 0:   
            return False 

    return True
    

N = 1000000
for i in range(0, N):
    print("Trying i =", i)
    if i%2==0 and is_prime(i):
        
        print(i, "is prime and even")   
        break
print("All done!")        
Trying i = 0
Trying i = 1
Trying i = 2
2 is prime and even
All done!

Once we reach a number that's prime and even, we stop the execution of the loop, and go to the next line (in this case, print("All done!"). Note that we already did something like this, with a return statement. Consider the following two functions

In [2]:
def print_even_prime1(N):
    for i in range(N):
        if i % 2 == 0 and is_prime(i):
            print(i, "is prime and even")   
            break
    
    print("All done!")
    
def print_even_prime2(N):
    for i in range(N):
        if i % 2 == 0 and is_prime(i):
            print(i, "is prime and even")   
            return
    
    print("All done!")    

There is a difference: print_even_prime1 will always print "All done!", whether it finds an even prime or not.On the other hand, print_even_prime2 will not print "All done!" if it finds an even prime, since if an even prime is found, the return statement will terminate the function.

*If you find yourself using break, consider whether it wouldn't be better to find a way to use return -- probably it would be better to use return.

If using while

Here is another (silly and inadvisable) thing you could try: using a while-loop to make an if statement. The following two pieces of code do the same thing.

In [3]:
ENGSCI_IS_FUN = True
while ENGSCI_IS_FUN:
    print("Wheee")
    break
Wheee
In [4]:
if ENGSCI_IS_FUN:
    print("Wheee")
Wheee

Consider the while "loop" (which isn't quite a loop...). If the condition (ENGSCI_IS_FUN) is true, then we print once, and then hit break immediately. That means that the loop executes for at most one iteration.

If the condition were false, we would not print anything, and go to the next line in the program.

Continue

The continue statement makes the loop go to the next iteration, stopping the current iteration. This is useful to, for example, save on computation time:

In [5]:
def is_prime(n):
    '''Return True iff n is prime
    Arguments:
    n -- a  non-negative integer
    '''
    if n <= 1:
        return False
    
    for i in range(2, n):  
        if i > 2 and i % 2 == 0:
            continue
        if n % i == 0:   
            return False 

    return True

The addition line makes it so that we don't try to compute n%i for even i that are larger than 2, since continue makes us skip whatever follows it, and proceed to the next iteration (where the for-loop increments the i).

(This makes sense, since if a number isn't divisible by 2 (which would already have been checked), it makes no sense to try to check if it's divisible by 4, 6, 8, ....)

Again, always consider whether continue is a good idea -- it might be, but perhaps there are better ways. In this case, the following will do nicely:

In [6]:
def is_prime(n):
    '''Return True iff n is prime
    Arguments:
    n -- a  non-negative integer
    '''
    if n <= 1:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    
    for i in range(3, n, 2):  
        if n % i == 0:   
            return False 

    return True