This notebook uses code snippets and explanations from this course.
So far, we have learned how to use Python as a basic calculator and how to store information in variables. Now we will set the first steps to an actual useful program. A lot of programming has to do with executing code if a particular condition holds. This enables a program to act upon its inputs. For example: an app on your phone might give a warning if the battery level is lower than 5%. This means that the program needs to check if the variable battery_level
is lower than the value of 5. We can do these checks using so called Boolean expressions. These Boolean expressions are the main element in probably one of the most used things in Python: if statements.
If you have questions about this chapter, please refer to the forum on Canvas.
A Boolean expression (or simply: boolean) is an expression that results in the type bool
in Python. Possible values are either True
or False
. Boolean expressions are the building blocks of programming. Any expression that results in True
or False
can be considered a Boolean expression.
So far you've mainly seen:
In [ ]:
print(type('this is a string'))
print(type(101))
print(type(0.8))
Now we're introducing:
In [ ]:
print(type(False))
print(type(True))
Here is a list of comparison operators used in Boolean expressions:
Operator | Meaning | True |
False |
---|---|---|---|
== |
equal | 2 == 2 |
2 == 3 |
!= |
not equal | 3 != 2 |
2 != 2 |
< |
less than | 2 < 13 |
2 < 2 |
<= |
less than or equal to | 2 <= 2 |
3 <= 2 |
> |
greater than | 13 > 2 |
2 > 13 |
>= |
greather than or equal to | 3 >= 2 |
2 >= 3 |
Remember that the single = is reserved for assignment! Boolean expressions look at variables but never change them.
In [ ]:
print(2 < 5)
print(2 <= 5)
print(3 > 7)
print(3 >= 7)
print(3 == 3)
print("school" == "school")
print("Python" != "SPSS")
The relevant 'logical operators' that we used here are: <, <=, >,>=,==,!=. In Python-speak, we say that such a logical expression gets 'evaluated' when you run the code. The outcome of such an evaluation is a 'binary value' or a so-called 'boolean' that can take only two possible values: True
or False
. You can assign such a boolean to a variable:
In [ ]:
greater = 5 > 2
print(greater, type(greater))
greater = 5 < 2
print(greater, type(greater))
Let's look at some examples. Try to guess the output based on the information about the operators in the table above. Hence, will the expression result in True
or False
in the following examples?
In [ ]:
print(5 == 5)
In [ ]:
print(5 == 4)
In [ ]:
print(10 < 20)
In [ ]:
print(10 < 8)
In [ ]:
print(10 < 10)
In [ ]:
print(10 <= 10)
In [ ]:
print(20 >= 21)
In [ ]:
print(20 == 20)
In [ ]:
print(1 == '1')
In [ ]:
print(1 != 2)
In [ ]:
boolean_expression = 5 == 4
print(boolean_expression)
Python also has so-called membership operators:
Operator | function | True |
False |
---|---|---|---|
in |
left object is a member of right object | "c" in "cat" |
"f" in "cat" |
not in |
left object is NOT a member of right object | "f" in "cat" |
"c" in "cat" |
We have already seen the operator in
being used for checking whether a string (single or multiple characters) is a substring of another one:
In [ ]:
print("fun" in "function")
We can only use membership operators with iterables. The following will therefore not work, because an integer is not iterable:
In [ ]:
print(5 in 10)
However, we can use membership operators with other types of 'containers', such as lists. We will discuss lists in much more detail later on, but they represent ordered sequences of objects like strings, integers or a combination. We can use in and not in to check whether an object is a member of a list:
In [ ]:
letters = ['a','b','c','d']
numbers = [1,2,3,4,5]
mixed = [1,2,3,'a','b','c']
In [ ]:
print('a' in letters)
In [ ]:
print('g' not in letters)
In [ ]:
print('d' in mixed)
In [ ]:
print(1 in numbers)
In [ ]:
print(3 not in mixed)
In [ ]:
print('a' not in 'hello world')
Finally, boolean operations are often performed using the boolean operators and
, or
and not
. Given two boolean expressions, bool1 and bool2, this is how they work:
operation | function | True |
False |
---|---|---|---|
bool1 and bool2 |
True if both bool1 and bool2 are True , otherwise False |
(5 == 5 and 3 < 5 ) |
(5 == 5 and 3 > 5 ) |
bool1 or bool2 |
True when at least one of the boolean expressions is True , otherwise False |
(5 == 5 and 3 > 5 ) |
(5 != 5 and 3 > 5 ) |
not bool1 |
True if bool1 is False , otherwise False |
(not 5 != 5 ) |
(not 5 == 5 ) |
Here are some examples of and
:
In [ ]:
letters = ['a','b','c','d']
numbers = [1,2,3,4,5]
In [ ]:
print('a' in letters and 2 in numbers)
In [ ]:
print("z" in letters and 3 in numbers)
In [ ]:
print("f" in letters and 0 in numbers)
Here are some examples of or
:
In [ ]:
letters = ['a','b','c','d']
numbers = [1,2,3,4,5]
In [ ]:
print('f' in letters or 2 in numbers)
In [ ]:
print('a' in letters or 2 in numbers)
In [ ]:
print('f' in letters or 10 in numbers)
Here are some example of not
:
In [ ]:
a_string = "hello"
letters = ['a','b','c','d']
numbers = [1,2,3,4,5]
In [ ]:
print(not a_string.endswith("o"))
In [ ]:
print(not a_string.startswith("o"))
In [ ]:
print(not 'x' in letters)
In [ ]:
print(not 4 == 4)
In [ ]:
print(not (4 == 4 and "4" == 4))
In [ ]:
print(not 'x' in letters)
print('x' not in letters)
In [ ]:
print(not 4 == 4)
print(4 != 4)
In [ ]:
print("test" != "testing" and 1 == 1 and 2 == 2 or 20 in [1, 20, 3, 4,5])
Not really, right? Luckily, Python has another trick to deal with this type of examples: all
and any
. Given a list of boolean expressions, this is how they work:
operation | function |
---|---|
all |
True if all boolean expressions are True, otherwise False |
any |
True if at least one boolean expression is True, otherwise False |
If you don't completely understand all()
and any()
, don't worry, you will not necessarily need them right now. They are just a nice alternative to make your code more readable and you may appreciate that in the future.
Here are some examples of all()
:
In [ ]:
letters = ['a','b','c','d']
numbers = [1,2,3,4,5]
In [ ]:
list_bools1 = ['a' in letters,
2 in numbers]
print(list_bools1)
boolean_expression1 = all(list_bools1)
print(boolean_expression1)
In [ ]:
list_bools2 = ['a' in letters,
20 in numbers]
print(list_bools2)
boolean_expression2 = all(list_bools2)
print(boolean_expression2)
Here are some examples of any()
:
In [ ]:
list_bools3 = ['f' in letters,
200 in numbers]
print(list_bools3)
boolean_expression3 = any(list_bools3)
print(boolean_expression3)
In [ ]:
list_bools4 = ['a' in letters,
20 in numbers,
2 in numbers]
print(list_bools4)
boolean_expression4 = any(list_bools4)
print(boolean_expression4)
Let's look at an example (modify the value of number to understand what is happening here):
In [ ]:
number = 2 # try changing this value to 6
if number <= 5:
print(number)
You can use as many if
statements as you like:
In [ ]:
number = 5
if number == 5:
print("number equals 5")
if number > 4:
print("number is greater than 4")
if number >= 5:
print("number is greater than or equals 5")
if number < 6:
print("number is less than 6")
if number <= 5:
print("number is less than or equals 5")
if number != 6 :
print("number does not equal 6")
But what if we want to have options for two different scenarios? We could just use a bunch of if
statements. However, Python has a more efficient way. Apart from if
we also have the else
statement for two-way decisions (modify the value of number
to understand what is happening here):
In [ ]:
number = 10 # try changing this value to 2
if number <= 5:
print(number)
else:
print('number is higher than 5')
Now Python always runs one of the two pieces of code. It's like arriving at a fork in the road and choosing one path to follow.
In [ ]:
age = 21
if age < 12:
print("You're still a child!")
elif age < 18:
print("You are a teenager!")
elif age < 30:
print("You're pretty young!")
else:
print("Wow, you're old!")
First the if
statement will be evaluated. Only if that statement turns out to be False
the computer will proceed to evaluate the elif
statement. If the elif
statements in turn would prove to be False
, the machine will proceed and execute the lines of code associated with the else
statement. You can think of this coding structure as a decision tree! Remember: if somewhere along the tree, your machine comes across a logical expression which is True
, it won't bother anymore to evaluate the remaining options! Note that the statements are evaluated in order of occurence.
Can you identify the difference between the code above and the code below? (Try changing age
)
In [ ]:
age = 21
if age < 12:
print("You're still a child!")
if age < 18:
print("You are a teenager!")
if age < 30:
print("You're pretty young!")
else:
print("Wow, you're old!")
Remember:
if-if
: your code wil check all the if
statementsif-elif
: if one condition results to True
, it will not check the other conditionsUnless you need to check all conditions, using if-elif
is usually preferred because it's more efficient.
Let's take another look at the example from above (we've added line numbers):
1. if number <= 5:
2. print(number)
3. else:
4. print('number is higher than 5')
You might have noticed that line 2 starts with 4 spaces. This is on purpose! The indentation lets Python know when it needs to execute the piece of code. When the boolean expression in line 1 is True
, Python executes the code from the next line that starts four spaces or one tab (an indent) to the right. This is called indentation. All statements with the same distance to the right belong to the same 'block' of code.
Unlike other languages, Python does not make use of curly braces to mark the start and end of pieces of code, like if
statements. The only delimiter is a colon (:) and the indentation of the code. Both four spaces and tabs can be used for indentation. This indentation must be used consistently throughout your code. The most popular way to indent is four spaces (see stackoverflow). For now, you do not have to worry about this, since a tab is automatically converted to four spaces in notebooks.
Take a look at the code below. We see that the indented block is not executed, but the unindented lines of code are. Now go ahead and change the value of the person
variable. The conversation should be a bit longer now!
In [ ]:
person = "John"
print("hello!")
if person == "Alice":
print("how are you today?") #this is indented
print("do you want to join me for lunch?") #this is indented
elif person == "Lisa":
print("let's talk some other time!") #this is indented
print("goodbye!")
We have seen that all statements with the same distance to the right belong to the same block of code, i.e. the statements within a block line up vertically. The block ends at a line less indented or the end of the file. Blocks can contain blocks as welll; this way, we get a nested block structure. The block that has to be more deeply nested is simply indented further to the right:
There may be a situation when you want to check for another condition after a condition resolves to True
. In such a situation, you can use the nested if
construct. As you can see if you run the code below, the second if
statement is only executed if the first if
statement returns True
. Try changing the value of x to see what the code does.
In [ ]:
x = float(input("Enter a number: "))
if x >= 0:
if x == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative number")
It's important to practice a lot with boolean expressions. Here is a list of them, which orginate from learnpythonthehardway. Try to guess the output.
In [ ]:
print(True and True)
In [ ]:
print(False and True)
In [ ]:
print(1 == 1 and 2 == 1)
In [ ]:
print("test" == "test")
In [ ]:
print(1 == 1 or 2 != 1)
In [ ]:
print(True and 1 == 1)
In [ ]:
print(False and 0 != 0)
In [ ]:
print(True or 1 == 1)
In [ ]:
print("test" == "testing")
In [ ]:
print(1 != 0 and 2 == 1)
In [ ]:
print("test" != "testing")
In [ ]:
print("test" == 1)
In [ ]:
print(not (True and False))
In [ ]:
print(not (1 == 1 and 0 != 1))
In [ ]:
print(not (10 == 1 or 1000 == 1000))
In [ ]:
print(not (1 != 10 or 3 == 4))
In [ ]:
print(not ("testing" == "testing" and "Zed" == "Cool Guy"))
In [ ]:
print(1 == 1 and (not ("testing" == 1 or 1 == 0)))
In [ ]:
print("chunky" == "bacon" and (not (3 == 4 or 3 == 3)))
In [ ]:
print(3 == 3 and (not ("testing" == "testing" or "Python" == "Fun")))
In [ ]:
print("test" != "testing" and 1 == 1 and 2 == 2 and 20 in [1, 20, 3, 4,5])
Write a small program that defines a variable weight
. If the weight is > 50 pounds, print "There is a $25 charge for luggage that heavy." If it is not, print: "Thank you for your business." If the weight is exactly 50, print: "Pfiew! The weight is just right!". Change the value of weight a couple of times to check whether your code works. Make use of the logical operators and the if-elif-else construct!
In [ ]:
# insert your code here
In [ ]:
my_string = "hello"
if my_string == "hello":
print("world")
Why is the last line in the following code red? Correct the mistake.
In [ ]:
my_string = "hello"
if my_string == "hello":
print("world")
What's wrong in the following code? Correct the mistake.
In [ ]:
my_string = "hello"
if my_string == "hello"
print("world")
What's wrong in the following code? Correct the mistake.
In [ ]:
my_string = "hello"
if my_string = "hello":
print("world")
In [ ]:
x = float(input("Enter a number: "))
if x >= 0:
if x == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative number")
A friend wants your advice on how much oranges he should buy. Write a program that will give the advice to buy 24 oranges if the price is lower than 1.50 EUR per kg, 12 oranges if the price is between 1.50 EUR and 3 EUR, and only 1 orange if the price is higher than 3 EUR. But also tell him that he should only buy them if the oranges are fresh; otherwise, he should not get any. Use nesting and the if-elif-else construct.
In [ ]:
orange_quality = "fresh"
orange_price = 1.75
# your code here