Introduction: Conditionals

We use conditionals all the time in our daily lives without even realizing it. However, they aren't written in Python. We use conditionals in choices ranging from deciding what to wear in the morning to life-changing decisions like selecting a job.

I would cross the street if the light turns green; otherwise, I would wait. If the sun comes up, I would get out of bed; otherwise, I would go back to sleep again. Okay, it's not quite that simple, but when we make decisions based on circumstances, our brain behaves similarly to a machine: it evaluates the conditions and acts on the results.

Conditions - usually in the form of if statements - are one of the key features of a programming language, and Python is no exception. If statements are control flow statements which allow us to run a particular code and make a decision only when a certain condition is met. Most of the time, this decision depends on the value of variables or arithmetic expressions.

Conditional statements represent the set of instructions that allow us to make these decisions and perform computations depending on whether the code (a specific Boolean constraint) evaluates to True or False. Therefore, in a programming language, there are often two parts to a sample of code: One which will be executed, if the condition is True, and another one, if it is False. In the upcoming chapter, you will get to experiement with conditionals with an extedend example!

conditions

College Application Example

Additional Material: Operators

Before starting looking at if and else statements, we will dive deeper into the basic operators that we will use in the next examples. The if, if-else or elif statements, that we will see, will contain these operators. Here is a short list of operators that we have included in our programs:

Assignment operators: = (assign)

Comparison operators: == (equal), != (not equal)

Logical operators: and (Returns True if both statements are true), or (Returns True if one or both of the statements are true)

It must be added that, in Python, == and = do not have the same meaning. = assigns a value to a variable, for example age=5 implies that the value 5 is assigned to age. In contrast, == is the equal sign, that we commonoly use in mathematics. The latter symbol is used to check whether two expressions give the same value. For instance, (x==y) would result in False if we had assigned different values to x and y.

If and else statements

In this example, we put ourselves in the shoes of a college applicant, who is looking to submit both his essay and grade transcript to his college of choice. The university's application portal verifies whether the application is successful by asking the applicant to type in Completed if the applicant wrote his essay and Sent if he sent his grades. The indented block will only be executed (the application will only be successful) if the words Completed and Sent are typed in. If the user enters any other set of words, nothing happens. Please remember to add quotation marks (" ") to the instructions that you want the applicant to see, as the text represents a string (a sequence of characters) and not including the quotation marks would give you a Syntax error.

In [3]:
essay_application = input("If you have completed your essay please type in 'Completed': ")
grades = input("If you have submitted your grades please type in 'Sent': ")
if essay_application == 'Completed' and grades == 'Sent':
    print('Application successful!')
If you have completed your essay please type in 'Completed': Completed
If you have submitted your grades please type in 'Sent': Sent
Application successful!

We will strengthen our code in case the applicant disregards the capital letter at the start of Completed and Sent. After all, the university doesn't want an applicant who has completed all of the required tasks to not be considered because of a technicality. In the following case, the applicant can type in completed and sent and his application will still be successful. As you can see, we used the expression or to make sure that the application portal also accepts the words completed and sent in addition to Completed and Sent.

In [46]:
essay_application = input("If you have completed your essay please type in 'Completed': ")
grades = input("If you have submitted your grades please type in 'Sent': ")
if (essay_application == 'Completed' or essay_application == 'completed') and (grades == 'Sent' or grades == 'sent'):
    print('Application successful!'')
If you have completed your essay please type in 'Completed': Completed
If you have submitted your grades please type in 'Sent':sent
Application successful!

We will now introduce the else statement by adding a code block that lets the applicant know that his application is unsucessful. It must be noted that, there can be an if statement without an else statement. However, it is not possible to have an else statement if previously there is no if statement. Furthermore, it is important to know that Python will never execute the if and the else statements together as they are mutually exclusive.

The university also decided to improve user experience by addressing applicants by their name. Hence, the variable name name was added to the code, and .format(name) inserts the applican't name into the brackets.

In [47]:
name = input('Enter your name please: ')
essay_application = input("If you have completed your essay please type in 'Completed': ")
grades = input("If you have submitted your grades please type in 'Sent':")
if (essay_application == 'Completed' or essay_application == 'completed') and (grades == 'Sent' or grades == 'sent'):
    print('Application successful, {}!'.format(name))
else:
    print('Application unsuccessful, {}!'.format(name))
Enter your name please: Alex
If you have completed your essay please type in 'Completed': completed
If you have submitted your grades please type in 'Sent':Sent
Application successful, Alex!

You are free to experiment with the code youself by selecting the cell containing the code and running the code in your Jupyter Notebook.

Elif statements

In the next example we will modify our code so that we get an introduction to the elif statement. Let's imagine that the university wants to let applicants know why their application is unsuccessful. Hence, it wants applicants to know whether the applicant failed either the essay or the grade requirement, or whether he failed both requirements.

In [49]:
name = input('Enter your name please: ')
essay_application = input("If you have completed your essay please type in 'Completed': ")
grades = input("If you have submitted your grades please type in 'Sent':")
if (essay_application == 'Completed' or essay_application == 'completed') and (grades == 'Sent' or grades == 'sent'):
    print('Application successful, {}!'.format(name))
elif (essay_application == 'Completed' or essay_application == 'completed') and (grades != 'Sent' and grades != 'sent'):
    print('Grade requirement failed, your application was unsuccessful, {}!'.format(name))
elif (essay_application != 'Completed' and essay_application != 'completed') and (grades == 'Sent' or grades == 'sent'):
    print('Essay requirement failed, your application was unsuccessful, {}!'.format(name))
else:
    print('Both requirements failed, your application was unsuccessful, {}!'.format(name))
Enter your name please: Alex
If you have completed your essay please type in 'Completed': Completed
If you have submitted your grades please type in 'Sent':not sent
Grade requirement failed, your application was unsuccessful, Alex!

ElifFlowchart

Since the code is getting longer and more complex, let's review it more clearly:

  1. The above code works in the exact same way as the code sections mentioned earlier in the chapter, with the only difference being the elif statement. As we know, the applicant will ony have a successful application when both grades and essay requirements are met.
  2. If the first if statement holds True, then the applicant will be successful. If it doesn't, we move on to the first elif statement.
  3. If the first elif statement holds True, it means that the grade requirement failed. If the statement holds False, we move on to the last elif statement.
  4. If that last elif statement holds True, then the essay requirement failed.
  5. Lastly, if the last elif statement fails, we automatically move on to the else statement, where both requirements fail. This else statement can be considered a default parameter as it always holds valid as long as all other statements in the code hold False.

The above code does function properly; however, it's not well structured and is error-prone. In this situation, we are not troubled by the repetition of elif statements . Nevertheless, with thousands of lines of code, it gets more difficult to differentiate the outcomes of the code. Thus, it is good practice in Computer and Data Science to keep your Code DRY (Don't Repeat Yourself!).

In the next example, we are improving the code by clearly marking the difference between a successful and an unsuccessful application with an else statement:

In [1]:
name = input('Enter your name please: ')
essay_application = input("If you have completed your essay please type in 'Completed': ")
if essay_application != 'Completed' and essay_application != 'completed':
    print('Essay requirement failed, your application was unsuccessful, {}'.format(name))
else:
    grades = input("If you have submitted your grades please type in 'Sent': ")
    if grades == 'Sent' or grades == 'sent':
        print('Application successful, {}!'.format(name))
    else:
        print('Grade requirement failed, your application was unsuccessful, {}!'.format(name))
Enter your name please: Alex
If you have completed your essay please type in 'Completed': Completed
If you have submitted your grades please type in 'Sent':s
Grade requirement failed, your application was unsuccessful, Alex!

Let's review the code again:

In this example, we used the same intuition as before, however the school now made sure that the application could only move on once the essay condition is satisfied. Now, the application process is sequential and more concise. Here, we see that we can integrate if, elif and else statements into a more general else statement.

Summary

To help you out, we have created for you an interactive example that summarizes the concepts that we have seen so far. This particular example asks you for your cat's age and converts that age to human years.

  1. Start by asking the user for his input. Make sure to treat the input as a floating number using float() or as an integer using int(). If you do not add any of these two options, you will get a Type Error as the conditions will not recognize the input as a number. In this case, float () was used as the user might decide to specify a more precise age for the cat (2.5,4.5,.. years old). If the user used int() and typed in a number such as 2.5, there would be an error.
  2. Add your if statement when you want to introduce your first condition. Remember to add ' : ' at the end of the line of code if you don't want to get a Syntax Error. Once you have written the line of code and pressed ' Enter ', Python will bring you to the following line with an indent. All indented lines of code will be executed as part of the condition that was set by the if statement.
  3. In this example, the first if statement is followed by an else statement because we want to seperate incalculable values (negative age) from calculable values. The else statement possesses all of the calculable values. The else statement will run only if the age value given is nonnegative.
  4. The else statement contains a number of elif statements that will only get executed if the previous if or elif statement is False. The if and elif statements contained in the else statement represent new conditions and thus you return to the same tabulation level than the first if (in the else statement).

    At the end, you cannot add an else to consider all other situations, as the other situations are already taken into consideration. Thus, it is essential to understand that the else only refers to the last if.

In [12]:
age = float(input('Age of the cat: ')) #float: treat user's input as a floating point number, which can possess decimal values 
if age < 0:
    print ('This cannot be true!')
else:
    if age == 0:
        print ('about 0 human years')
    elif age == 1:
        print ('about 14 human years')
    elif age == 2:
        print ('about 22 human years')
    elif age > 2:
        human = 22 + (age -2)*5
        print ('Human years: ', human)
  
Age of the cat: 7
Human years:  47.0

Introduction: Iterations

Software programs come in handy when you have to do a lot of the same things over and over again. They can perform the same calculations with minor, but important, variations without complaining or getting bored and tired, like humans would. As a result, we use machines to perform massively repetitive tasks that we would rather not do.

We need effective ways of asking the machine to perform these repetitive tasks; we don't want to have to pause and tell the computer to repeat the process for a slightly different case every time it completes one iteration. We just want to tell the computer once, “Do this job 1000 times with slightly different conditions and report back to me when you are finished”. In general, we don't want the machine to stop its calculations and ask us what it should do if its calculations produce a particular result. " Look, if you get result X during your calculations, do this. If you don't, do this instead,” we may suggest. As such, combining conditionals and iterations, which are essential when completing these computational tasks, allows the user to control the flow of a program. In the following chapter, we will see how iterations are implemented in a number of ways in Python.

Iterations and loops are conceptually similar, and the terms are often used interchangeably. The next few paragraphs illustrate how iterations are used on various containers and in various contexts. Now, let's get to some illustrative examples!

For Loops

Python for loops are widely used in data science to loop through an iterable object (such as a list, tuple, sequence, etc.) and perform the same action for each entry. A for loop, for example, allows you to iterate through a list of objects, performing the same action on each one.

The for command must end with a colon character, and the body of the for-loop is whitespace-delimited.

ForLoopFlowchart

Simple Iteration

The example below shows how to iterate over a list of people:

In [53]:
people = ['Alessandro', 'Alexandre', 'Sara']
for person in people:
 print(person)
Alessandro
Alexandre
Sara

The for loop instructs the Python interpreter to iterate through the people list (this shouldn't necessarily be a list and could be another type of container object). The Python interpreter will exit the for-loop without running its body if the iterable (people) is empty. The first element of people is then assigned to person (variable person becomes defined if it was not previously defined). The script then runs the indented code block, which prints the person's name (Alessandro) on the computer. The iteration then moves on to the list's second element, repeating this same process.

Enumerating iterations

The enumerate function in Python makes it simple to count the number of iterations:

In [54]:
people_list = ['Alessandro', 'Alexandre', 'Sara']
for n, person in enumerate(people_list):
 print(n)
 print (person)
0
Alessandro
1
Alexandre
2
Sara

The above code iterates over the list people as before, but instead of assigning Alessandro, Alexandre, and Sara to person, it also assigns the iteration number (starting at 0) to n.

Iterating over a file

In [57]:
filename = ('/Users/Documents/my_file.txt')
with open(filename) as file:
 for line in file:
    print(line)

PS: The code block is just an example. Do not run the cells if you do not possess an adequate file with filename /Users/Documents/my_file.txt.

The above code has the role of assigning filename to file and proceeds by printing each line element in file.

Iterating over ranges

One can also iterate over a range. In this example, the range function generates integers ranging from 0 to 100, starting from 0 and printing all multiples of 5. The resulting range may be iterated using the for command, and the results appear on the screen.

In [58]:
for n in (range(0,100,5)):
 print(n)
0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
95

Iterating over a string

Although strings are primitive data types, they can be viewed as more complex data structures that contain a number of different elements. As a consequence, it is possible to iterate across a string in the same way that it is possible to iterate across a set. In the example below, note how we iterate over a nine-letter string:

In [59]:
string = 'HIJKLMNOP'
for element in string:
 print(element)
H
I
J
K
L
M
N
O
P

Nested iterations

An iteration within an iteration is known as a nested iteration. Nested iterations are very common in Python code because they are a great way to combine values in order to construct permutations of those values. The nested iteration below, for example, produces 16 di-nucleotide permutations of the four DNA nucleotide bases.

In [60]:
bases_list = ['A', 'G', 'C', 'T']
for base_1 in bases_list:
 for base_2 in bases_list:
     print(base_1 + base_2)
AA
AG
AC
AT
GA
GG
GC
GT
CA
CG
CC
CT
TA
TG
TC
TT

While Loops

As stated earlier in this course, with most of the Python code, even a novice can make a fair guess at what a line of code does simply by looking at the meaning of the words in English. Another such example is the while loop, which means "keep looping while this statement holds true" in simple terms.

WhileLoopFlowchart

Consider the following scenario:

In [61]:
x = 2
while(x < 7):
 print(x)
 x += 1 #incrementing x by 1
2
3
4
5
6

In this code, x is assigned the value 2. We then move onto the loop, which will be repeated as long as x is less than 7. There is a colon at the end of this line of text, followed by a four-space line indentation on the next line. For each loop, this indented code will be executed. The print statement shows the value of x on the screen before incrementing the value of x by one. This will print the values 2 to 6 (not 7, since x must be less than 7) to the screen. It's worth mentioning that if the increment command had been omitted, x would have been set to 2 and the loop would have proceeded indefinitely; we would have ended up with an infinite loop. When writing code, keep an eye out for these. Recheck that you haven't mistakenly created an endless loop if a program or procedure hasn't terminated for a much longer time than expected.

EndlessLoopMeme

Do-while loop

Do-while loops are a variant of the basic while loops. Although, they do not exist in Python themselves, we can write a Python program that functions like a do-while loop. As stated previously, in a while loop the condition is checked before running the loop. Hence, with a basic while loop, if the condition is not met, then the body of the loop is not executed. To avoid such a situation, with a do-while loop the computer will first execute the body of the loop and then check whether the condition is fulfilled. As long as the condition holds, the loop will keep running. Once the condition is not fulfilled anymore, the next statement is executed. A do-while loop can be quite useful when one wants to initialize a program and make the loop run at least once.

In [62]:
i = 7  
while True:  
    print(i)  
    i = i + 1  
    if(i > 6):  
        break  
7

In the code above, we see that although i>6, the loop will run at least once and the print statement will print 7 on your screen. There is no initial barrier to entry, which will stop the loop from running at least once, if i>6.

DoWhile_LoopFlowchart

Break Statements

Break is a Python command that leads to a program exiting a loop early. Even if the for loop hasn't run for a defined number of times, break allows the program to exit it. Morevoer, even if the logical condition that determines the loop is still True, break allows the program to exit while loops. Below are two examples of using break in a for loop and a while loop:

In [5]:
for i in range(50):
    print(i)
    if i == 5:
        break
print('We have exited the loop.')
0
1
2
3
4
5
We have exited the loop.

When the loop reaches i=5, break comes into play and the program exits the loop. In the next example, we will see how break works in a while loop:

In [6]:
while True:
    get_out = input('type g to exit the loop: ')
    if get_out == 'g':
        break
print('We have exited the loop.')
type g to exit the loop: j
type g to exit the loop: g
We have exited the loop.

The while loop above asks the user for his input and keeps asking the user for his input until the user inserts g. At this point, we have exited the loop and the program stops.

Pass Statement

Pass statements are useful when a segment of code is not fully finished but will be implemented in the future. Indeed, the pass allows software developers to keep incomplete functions and loops, which would result in an error and which have no functional purpose. In this way, the parts which are not finished will not block the whole program from working.

In [66]:
sequence = {'w', 'o', 'r', 'k'}
for value in sequence:
    pass

Continue Statements

The keyword continue causes the program to stop running code in a loop and return to the initial for statement. Note that the keyword break is used to escape a loop. Continue is similar to stop, except it allows the program to stop the current iteration of the loop and begin the next one at the start.

Below, we have demonstrated how to use a continue statement for a for and a while loop:

In [67]:
for i in range(7):
    if i==1:
        continue
    print(i)
0
2
3
4
5
6

When the code above is run, the number 1 is not printed at all. This is because when i=1, the program reaches the continue statement. Thus, the line print(i) isn't executed when i=1, and the program returns to the initial 'for statement' with the following number i=2. Below, we will see how the continue statement works with a while loop:

In [68]:
n = 8
while n > 0:
    n -= 1 #decrement (decrease) of 'n' by 1
    if n == 1:
        continue
    print(n)
print('The loop has ended.')
7
6
5
4
3
2
0
The loop has ended.

This time, when n is 1, the continue statement causes the iteration to end. As a consequence, the number 1 is not printed. We then return to the initial while loop condition and re-evaluate it. If it is still valid, the loop resumes until it reaches n equals 0.

Else Statement

An else statement can be added at the end of any loop. In the example below, the body of this else statement will run only if the loop was not exited via a break statement:

In [13]:
for number in [1, 3, 5]:
    if number == 2:         
        print(number, ' ...break!')
        break
    print(number, ' ...keep iterating')
else:
    print("If you are seeing this, then the loop completed without a 'break'.")
1  ...keep iterating
3  ...keep iterating
5  ...keep iterating
If you are seeing this, then the loop completed without a 'break'.

The section of code above will exit the for loop if it identifies 2 in [1,3,5]. In this case, however, as there is no 2 , the code will never run the break statement. It will print all of the numbers in the list given and complete the loop without a break.

What is the difference between a for loop and a while loop?

For Loop: On the one hand, computer scientists typically use the for loop when they know with certainty the number of times that the loop needs to be excuted.

While Loop: On the other hand, the while loop is necessary when a programmer isn't certain about the number of times that the loop needs to be excuted beforehand.

Advanced Example: Estimation of $\pi$ for Quantitative Analysis

Now that we know the basic functioning of the for-loop, let us look at some more interesting examples to demonstrate how versatile this tool really is.

How can we find the value of π using a for loop?

The main idea is to use the formula for the area of circle, i.e. $ A = \pi\times r^2 $ . We will create a set-up that will allow us, thanks to random numbers, to find $\pi$. We’ll create a square of length 2 and a circle of radius 1, such that the circle is inside the square. Where, $A_s$ is the area of the square and $A_c$ is the area of the circle.

CircleWithoutPoint

What we will do now is generate pairs of random numbers $(x, y)$, such that $|x| < 1, |y| < 1$. This way, we can represent each pair of numbers as a point in the square. The objective now is to find the area in green and extract from that the value of $\pi$. But how does this work? The key is looking at the ratio between the area of the circle and the area of the square. We know $A_s =2\times 2=4 $, and $A_c =\pi\times 1^2 =\pi$. Thus,

$$\frac{A_c}{A_s}=\frac{\pi}{4}, \quad\text{and}\quad \pi=4\frac{A_c}{A_s}$$

Now, we can estimate the ratio $\pi = 4 \frac{A_c}{A_s}$ , by generating random points and counting how many points fall inside the circle and dividing by the total number of points.

$$\pi\approx4\frac{\text{Number of points in the circle}}{\text{Total number of points}}$$

To check whether a point is in the circle or not, we used the following condition $x^2 + y^2 ≤ 1$. This comes from the equation of a circle, $x$ and $y$ are coordinates of a random point on the circle and one is the length of the radius.

CircleWith100Points

Here, we generated 100 random points. 77 points were in the circle, while 23 were outside. We can now calculate our ratio and multiply it by 4, as explained previously.

$$4*\frac{77}{100}=3.08\approx \pi$$

CircleWith1000Points

Our accuracy increases with the number of points generated. Here, we generate 1000 points, and we got:

$$4*\frac{782}{1000}=3.128\approx \pi$$

Let us now try to get a numerical estimation with the following code. The code computed pi by looking only at one quadrant of a circle. However, it does not change anything to the formula if we use one quadrant or the whole circle. Indeed, as it is a ratio, the numerator and the denomiator increase in the same proportion if we use the whole square.

The previously mentionned formula ( $\frac{\text{Points in the circle}}{\text{Total number of points}}$ ) tells us how to mathemically procede. If we generate thousands of points, then we can precisely compute $\pi$.

The output of the code gives us a representation of $\pi$. In green, you can see the points in the circle and in red the points in the square but not in the circle.

In [14]:
import matplotlib.pyplot as plt
       
import numpy as np  #import this library
from random import random

in_circle = 0 #counter that counts the points in the circle 
n = 10**4 #number of iterations

x_in, x_out, y_in, y_out = ([]for i in range(4)) #defining 4 arrays

for _ in range(n): #generating n random points (x,y) between 0 and 1, the for loop iterates n times
    x = random() #by default random gives values between 0 and 1
    y = random()
    if x**2+y**2 <= 1: #test if (x,y) is inside the unit circle
        in_circle += 1 #if point is inside we increase our counter by 1 
        x_in.append(x) #add one to the count 'x_in'
        y_in.append(y)  #add one to the count 'y_in'
    else: 
        x_out.append(x)  #add one to the count 'x_out'
        y_out.append(y)  #add one to the count 'y_out'
pi = 4*in_circle/n   # calculate pi by multiplying by 4 the ratio of points in the circle to the total amount of points
print(pi)  #show the reuslts for pi calulcated that way

fig, ax = plt.subplots()  #it returns a figure
fig.suptitle('Pi approximation with for loop') # it gives a name to the figure
ax.set_aspect('equal') # x and y axes are similar
ax.scatter(x_in, y_in, color='g', marker='o', s=4)  #it indicates the color of the points in the circle (green), as well as the form (o) and the size (4) of the points
ax.scatter(x_out, y_out, color='r', marker='o', s=4) # it indicates the color of the points outside the circle (red) as well as the form (o) and the size (4) of the points
plt.show()  #it shows the plot
3.1236