Conditionals

Introduction

Imagine that you invite a few friends to dinner at your place. At the beginning of the meal, one guest calls your attention: "I'm sorry, but I don't have any fork..."

Like everyone else, you will understand his request implicitly as: "Could you please give me a fork?"

Since you are having dinner, you will also assume that the requested object is a small fork which is used to eat, of course not a farmer's fork...

Therefore, you will go to your kitchen. If you don't find any fork there, you will probably stressed out for a few seconds then you will tell yourself: "Well... Maybe I can borrow one from the neighbor..."

The bottom line of this story is that you have to keep in mind that your computer is not as clever as you. At least at our basic programming level, your computer is totally unable, inter alia, to understand any implicit assertion, to interpret an assertion according to the context, or to improvise in an unexpected situation.

It means that you have to give him precise instructions about what to do in each possible situation. Fortunately, you use a programming language to speak to your computer. Programming languages, like Python, use specific predefined (in jargon : native) structures to deal with those cases. What will follow will show you how.

The conditionals allow us to tell the computer what to do in specific situations.

We will start with a concrete example: a user connection interface. To make the explanation easier to follow, let simplify the example as much as possible.

Application : User connection interface

If and else

We will basically define an ID and a password that will be required to connect to our fictitious server. In a real situation, the user would have registered those informations previously. Don’t forget to add **""** around the desired terms to set their type as strings.

In [1]:
ID = "Euler"
password = "271"

Then, we need to define the data given by the user. We use the function input to let the user type his personal information.

In [2]:
ID = "Euler"
password = "271"

user_ID = input("Enter your ID : ")
user_password = input("Enter your password : ")
Enter your ID : 564
Enter your password : 444

At this point, there are two different situations. The user may either gives the required informations, or he may not. In the former situation, he will successfully connect. In the latter, he will not have access to the program. We can represent the case in the following pseudocode.

If user gives correct informations:
    access the program
Else:
    don't access the program

In our simplified example, we only have one registered user. Now, let assume now that they are plenty of them. To successfully connect, our users must give the correct ID AND the correct password. This means that the given ID must be equal to the registered ID as well as the given password must be equal to the registered one. In addition, a message will be printed to enable the user to understand whether or not the connection was succesful.

Let's insert the printing task into our pseudocode:

If ID is the same as user_ID AND password is the same as user_password:
    print : Welcome (user_name) ! You are connected.
    access the program
Else:
    print : Invalid ID or password
    don't access the program

Python is a programming language that is very intuitive to use. The defined Python syntax for the conditionals is quite similar to what we have written in our pseudocode. It looks like this:

In [3]:
if ID == user_ID and password == user_password: #Both inputs are correct
    print("Welcome {} ! You are connected.".format(user_ID)) #the method format inserts elements into the brackets
    user_connected = True
else: #The condition, that both ID and Password are correct, is not met
    print("ID or password are invalid")
    user_connected = False
ID or password are invalid

Yes you can

What have we done so far? We have used the conditionals **if** and **else** to differentiate the two situations.

Then, we have defined a new user_connected variable which, if wanted, may be used later on to let the user continue in the program.

**if** and **else** have the following use in our little example:

  1. **if** : If the user types the correct ID **and** the correct password, he will get a personalized welcoming message and the variable user_connected will be **True**.

  2. **else** : In all other situations, he will get a personalized failure message and user_connected will be **False**.

Each of those two conditions is exclusive. Python will execute either the **if** (and subsumed tabulated lines), or the **else**. It will never do both.

You can check it by running the following code. You just have to select the cell and press ⌃↩. Try all situations with correct and incorrect informations.

PS : We add the last line to let you check if the user is connected or not. If you get **True**, the user is virtually connected; if you get **False**, he is not.

In [4]:
ID = "Euler"
password = "271"

user_ID = input("Enter your ID : ")
user_password = input("Enter your password : ")

if ID == user_ID and password == user_password: #Both inputs are correct
	print("Welcome {} ! You are connected.".format(user_ID))
	user_connected = True
else:
	print("invalid ID or password") #The condition, that both ID and Password are correct, is not met
	user_connected = False

print(user_connected)
Enter your ID : Toni
Enter your password : 25
invalid ID or password
False

Digression : Operators

As you have probably noticed, we use a specific sign to make Python understand that two objects are equals : the sign **==**. This is an operator. We don't use **=** because this sign already have another meaning in Python. It means that we attribute a value to a variable. For more information, take a look at the ad hoc tutorial.

The operators are often quite intuitive. Here is a list of the most commonly used comparison and logical operators: Comparison Operator | Signification -------- | ----------- A == B| If the values of A and B are equal, then the condition becomes true. A != B| If values of A and B are not equal, then condition becomes true. A > B| If the value of A is greater than the value of B, then condition becomes true. A < B| If the value of A is less than the value of B, then condition becomes true. A >= B| If the value of A is greater than or equal to the value of B, then condition becomes true. A <= B| If the value of A is less than or equal to the value of B, then condition becomes true.

Logical Operator Signification
A and B If both A and B are true then condition becomes true.
A or B If A is true, or B is true, or both are true then condition becomes true.
not A Used to reverse the logical state of its operand.

Back to application : User connection interface

Elif

As you may think, two conditions are not enough. Indeed, the user knows that he entered an incorrect ID or password, but he does not know which one is incorrect (or if both are incorrect).

Consequently, in Python, we can add a supplementary exclusive conditional called: **elif**. It is an abreviation for the terms 'else if'. In addition, please understand that Python read an **elif** only if the previous condition is **False**. It quite makes sense since **else** means that the first conditions is false.

You can check the new code by running the following cell:

In [5]:
ID = "Euler"
password = "271"

user_ID = input("Enter your ID : ")
user_password = input("Enter your password : ")

if ID == user_ID and password == user_password: #Both inputs are correct
    print("Welcome {} ! You are connected.".format(user_ID))
    user_connected = True
elif ID != user_ID and password == user_password: #Only the ID is not correct
    print("Invalid ID. Please enter a correct ID.")
    user_connected = False
elif ID == user_ID and password != user_password: #Only the Password is not correct
    print("Invalid password. Please enter a correct password.")
    user_connected = False
elif ID != user_ID and password != user_password: #Both inputs are not correct
    print("Both ID and password are invalid. Please enter correct informations.")
    user_connected = False

print(user_connected)
Enter your ID : John
Enter your password : ddd
Both ID and password are invalid. Please enter correct informations.
False

Our code follow this path :

  1. **if** (first situation): If the user types the correct ID **and** the correct password, he will get a personalized welcoming message and the variable user_connected would be **True**.
  1. **elif** (second situation) : Else, if only the ID is incorrect, the user he will get an ad hoc message and user_connected will be **False**.
  1. **elif** (third situation) : Else, if only the password is incorrect, the user he will get an ad hoc message and user_connected will be **False**.
  1. **elif** (fourth situation) : Else, if both ID and password are incorrect, the user he will get an ad hoc message and user_connected will be **False**.

This code does work; nevertheless, it's not very well designed. As you can see, several lines are copy-pasted. In this example, it is not cumbersome since we only have four situations. However, imagine if you have hundreds of situations and thousands of lines of code, it may be hardly manageable.

As a principle, you should avoid having several times the same line. In Jargon: You should keep your Code DRY (Don't Repeat Yourself!)

Let's improve our code in order to delete copy-pasted lines:

In [6]:
ID = "Euler"
password = "271"

user_ID = input("Enter your ID : ")
user_password = input("Enter your password : ")

if ID == user_ID and password == user_password: #Both inputs are correct
    print("Welcome {} ! You are connected.".format(user_ID))
    user_connected = True
else: 
    if ID != user_ID and password != user_password: #Both inputs are not correct
        invalid_item = "ID and password"
    elif ID != user_ID: #Only the ID is not correct
        invalid_item = "ID"
    elif password != user_password: #Only the password is not correct
        invalid_item = "password"
    print("Invalid {}. Please enter a valid {}".format(invalid_item, invalid_item)) 
    user_connected = False

print(user_connected)
Enter your ID : Euler
Enter your password : 271
Welcome Euler ! You are connected.
True

Our code follows this path :

  1. **if** : If the user types the correct ID **and** the correct password, he will get a personalized welcoming message and the variable user_connected would be **True**.
  1. **else** : Else, user_connected will be **False** and the user will get a message telling him that he has entered invalid information. This message tells him what is invalid depending on the value of the variable invalid_item in the following sub-conditions :

    2.1 **if** : If both ID and password are incorrect, invalid_item will take the value "ID and password"

    2.2 **elif** : Else, if only ID is incorrect, invalid_item will take the value "ID"

    2.3 **elif** : Else, if only password is incorrect, invalid_item will take the value "password"

At this point, you may ask yourself : "Wait... There are four situations. Why don't we replace the last **elif** with an **else**?"

It is a good point! From what we have seen so far, you are right. Nevertheless, a rule in programming is that you should not blindly trust the user. He may do something unexpected. In this case, you will get an error message from the system. For you, it's nothing much; it will even help you to find your mistake. However, the user is not supposed to know how to react in those kind of situations. It could be quite a frustrating experience for him. That's not what you want, right?

Consequently, it is more favorable to put an **elif** and then add a final **else** in order to deal with any unexpected error. The user will not get any further information about his mistake, but at least, he will not get an incomprehensible message error from the system.

If you have time to waste, you can try printing the last message by entering some unexpected input. Good luck!

In [7]:
ID = "Euler"
password = "271"

user_ID = input("Enter your ID : ")
user_password = input("Enter your password : ")

if ID == user_ID and password == user_password:
    print("Welcome {} ! You are connected.".format(user_ID))
    user_connected = True
else: 
    if ID != user_ID and password != user_password:
        invalid_item = "ID and password"
    elif ID != user_ID:
        invalid_item = "ID"
    elif password != user_password:
        invalid_item = "password"
    else:
        invalid_item = "data"
        print("Something went wrong. Please retry to submit your ID and password.")
    print("Invalid {}. Please enter a valid {}".format(invalid_item, invalid_item))
    user_connected = False

print(user_connected)
Enter your ID : John
Enter your password : ??
Invalid ID and password. Please enter a valid ID and password
False

To sum up what we have learned about conditionals

  1. Always start with an **if** to create your first condition. Don't forget to add : at the end of the line. Python will automatically add a tabulation to the following line. All the following lines with this tabulation will be included in you first condition.

  2. Then you can create other conditions by adding as many **elif** as you like. You can also start new chains by adding new **if**.

    • Python will read an **elif** only if the previous condition is **False**.
    • Python will always read an **if** (of course, it will not always execute the subsumed instruction; only if the condition is **True**...)

    Keep in mind that each **if** or **elif** is a new condition; thus, you have to return to the same tabulation level than the first **if**.

  3. At the end, you can put an **else** for all other situations. (Attention, an **else** only refers to the last **if**.)

    If you're working with a user input, it's recommended to finish with an **else** in order to deal with all the other (unexpected) situations.

To make sure that you master the conditionals, you can play with the following code by changing parameters B, C, D and try to predict what will be the output:

In [8]:
A = 1
B = 0
C = 0
D = 0

if A == B:
    print("A is equal to B") #always read (of, only executed if A==B)
if A == C:
    print("A is equal to C") #always read
elif A == D:
    print("A is equal to D, but not to C") #only read if A!=C, independent from A==B
if A == D:
    print("A is equal to D") #always read
else:
    print("A is not equal to D") #only refer to A==D, not to A==B or A==C !
A is not equal to D

Iteration

In programming, there are two main methods to execute a task multiple times, we use the **for** –loop as well as the **while**-loop; The recursion method is also an iteration; however, it will unfortunatly not be covered in this tutorial

For

Imagine you have a list, which you can give whatever name you want. Also, this list may contain any variables you like. In the example below, let us call the list elements and insert several car brands.

It is important to say that For-loops can be used with many different types of objects. These are called iterable objects. For now, let's stick to the list you can see below.

In [9]:
elements = ["VW" , "Porsche" , "Toyota" , "Mercedes" , "Chevrolet" ,"Suzuki" ]

To print every element separatly, we can go through the list systematically. For this task though, we need to use a second variable - e.g. we can use following method:

In [10]:
for carname in elements:
    print(carname)
VW
Porsche
Toyota
Mercedes
Chevrolet
Suzuki

At every point in the list, we assign a value from the list to the variable carname and print it at the end. It's comparable to a box filled with a lot of stuff. The variable carname represents an object you just took out of that box and you compare it to a given criteria - e.g. is the object eatable or not.

Keep in mind that the name carname is totally arbitrary. You can name it BenficaIsTheBestFootballTeamInEurope; it will work to !

There is also the possibility to loop through a set of numbers at a set range. For example, if you want to print all numbers, which are a multiple of 3 until it reaches of number 100, you can use the **for**-loop with an easy approach.

In [11]:
for x in range(3,100,3): # range(3, 100, 3) <=> from 3 to 100, only multiples of 3
    print(x)
3
6
9
12
15
18
21
24
27
30
33
36
39
42
45
48
51
54
57
60
63
66
69
72
75
78
81
84
87
90
93
96
99

Within the range function, we define the starting point, the end point as well as the interval, we use to add to our starting point.

Break-Statement

If we are interested in a particular value of the list, and we want to stop the loop at a given value from continuing, we can use the so-called **break** statement. With the help of the **break** statement, we can leave the **for**-loop and continue with the next non tabulated line of code in our program. This **break** statement looks as following:

In [13]:
for carname in elements:
    if carname == "Toyota":
        print("reached break-command")
        break
    else:
        print(carname)
VW
Porsche
reached break-command

You can compare the **break** statement to searching a box for a certain element or certain number of elements. When you find whatever you were looking for, or you have taken the amount of things out of the box you needed, you stop searching for any other items and you go to the next task.

Continue-Statement

If our program should execute a piece of code for every value except a particular one, we can use the **continue** statement. **Continue**, therefore, helps us to skip certain values of the **for**-loop. For example, you roam through a box and for every item you take out of this box, you do a certain task, let's say put it in another box. Nevertheless, if you find a specific item that you don’t want in the new box, you just skip it.

In [12]:
for carname in elements:
    if carname == "Toyota":
        print("we wont print this carname, but continue the loop")
        continue
    else:
        print(carname)
VW
Porsche
we wont print this carname, but continue the loop
Mercedes
Chevrolet
Suzuki

Else-Statement

With the help of the **else** statement at the end of a loop, we can execute a certain step of code. Imagine you roam through a box of things where you take every item out. Thanks to the **else** statement you can put a piece of paper inside the box with a message.

In [14]:
for carname in elements:
    print(carname)
else:
    print("all items were checked")
VW
Porsche
Toyota
Mercedes
Chevrolet
Suzuki
all items were checked

While

With the **while**-loop, we get the possibility to loop through a piece of code a finite or an infinite number of times. It is defined by a true or false statement. Imagine, for example, that you drive your car on the street. While driving, you should check your speed systematically. In a code, this example would look this :

PS: The following example is just an analogy. Do not run the cells because the functions are not defined.

In [ ]:
while driving():
    checkSpeed()

Where driving() and checkSpeed() represent two defined functions. The **while**-loop consists of the same functionalities as the **for**-loop.

Break-statement

If you want to stop the loop, e.g. whenever a certain value occurs, you can use the **break** statement. Imagine again that you arrive at your destination, you will stop your car and leave. In code, this will look like this:

In [ ]:
while driving():
    if atDestination():
        print("Arrived at your destination")
        break
    else:
        checkSpeed()

Continue-statement

The **break** statement interrupts the loop and quits it. The second method is similar to the **continue** statement of the for-loop. With the continue-statement we can skip a certain case in our loop. For instance, while you are driving, there is a car, which breaks all the rules and hustles you in your lane, you can ignore him. In the while loop this looks like this:

In [ ]:
while driving():
    checkSpeed()
    if meanDriverArrives():
        continue
    else:
        checkSpeed()

To sum up what we have learned about iteration

Most importantly, we have to remember the different applications of the for and the while loop.

**for** **while**
The **for**-loop is used where we already know about the number of times loop needs to be excuted The **while**-loop is used in situations where we do not know how many times loop needs to be excuted beforehand.

**continue** Statements keep iterating after a certain value was found.

**break** Statements will stop the iteration after a certain value was found.

Thanks to this introduction into the iteration you should now be able to handle the most important things of this topic.