if-else
statementsBy the end of this lesson, you should be able to:
In the previous three lessons, you learned how to write sequential Python statements. Sequential statements refer to sequence of commands that are executed one after the other in the given order. In Lesson 4, you learned about functions which execute a named block of code when a function call is invoked. This lesson discusses conditional statements.
Conditional statements are Python commands that enable the execution of blocks of code based on the satisfaction of specific condition(s). Such commands exist in almost all structural and procedural programming languages. This conditional execution of code blocks set up multiple mutually exclusive execution paths in program code.
We start simple by introducing the if
statement. Then, you
will gradually expand the if statement into if-else
statements, then elif
statements, and finally nested
if-else
statements. In addition, we look deeper into simple
and compound logical statements.
if
Statements
The simplest conditional statement is the if
statement. As
the name suggests, a block of code is executed 'only if' a specific
condition is satisfied. The Python syntax for if
-statements
is:
if
Statement
if <logical expression>:
<block of code>
The first line starts with the keyword if
. This keyword is
followed by a space, then by a logical expression, followed by a colon (:
).
As you may recall from Lesson 3, a logical expression is an expression
that evaluates to either True
or False
.
The if
defines the start of a code block. Like the function
def
line, all code that belongs to the if
are
indented with the same indentation.
if
blocks may be used within main program code or within
functions, or within other if
blocks (these are nested
if
s.)
Some simple if statements:
if cost > 0.00: # compares variable to float
if
weight < 100: # compares variable to int
if
name == "David": # compares variable to string
if
first >= last: # compares variable to variable
if
result == True: # compares variable to boolean
if
result: # tests boolean
(which has the same effect as the line above)
It is possible, but not particularly useful, to write:
if 3 > 5: # compares raw number to raw number
if
True: # tests True
as these statements always evaluate to either False
or True
,
which is pointless. Useful if
s always involve a variable.
A more common design mistake is to use a statement that theoretically
could evaluate to True
or False
, but practically
evaluates to a fixed Boolean value. An example of such statement is the
following:
if exam_score > 200:
print('Good score')
In the context of a exam a valid score is a number between 0 and 100,
the above statement always, practically speaking, evaluates to False
since no valid score is ever greater than 100. Such code is redundant
and should be avoided.
To understand the importance of the above discussion, I invite you to put on some special goggles and look into the mind of a successful programmer. When looking, do not be distracted by the variety of commands and complex statements in the programmer's mind. Focus on how the mind operates during coding.
You should observe that the mind is not only focused on writing the current line of code, but it predicts how the overall program behaves with some expectation of outputs. So, the mind is coding without losing the big picture and while keeping an eye on the expected output. Such a mind is unlikely to write redundant statements.
Alas! We do not have such goggles to enjoy looking into good programmers' minds. However, we can imitate these good programmers in their good programming practices. Through some patience and diligence, you could be one of them.
The following trivial function uses an if
to determine if
an exam score is a pass:
# Constants
MINIMUM_PASS = 50
def pass_exam(score):
"""
-------------------------------------------------------
Determines if score is a pass.
Use: passed = pass_exam(score)
-------------------------------------------------------
Parameters:
score - numeric score (0 <= float <= 100)
Returns:
passed - True if score >= MINIMUM_PASS, False otherwise (bool)
-------------------------------------------------------
"""
passed = False
if score >= MINIMUM_PASS:
passed = True
return passed
The function sets a default value for the variable
passed
, and that variable is changed only when the if
condition
is triggered.
if-else
Statements
if-else
Statement:
The if
statement provides a mechanism to execute code when
a condition is satisfied. The if-else
statement provides
alternate code if the condition was not satisfied.
The structure of the if-else
statement is as follows:
if - else
Statement
if <logical expression>:
<code block 1>
else:
<code block 2>
Observe how the else
command appear on a separate line and
has the same indentation as the if statement. Also, observe how
code block 1 and 2 are both on the same indentation level.
Similar to the if-statement, in an if-else
statement both block 1 and 2 may contain a single line or multiple lines
of code. It is illegal to leave either block with no lines of code.
Remember to include the colon after the keyword else
. This
is a common syntax error among students learning Python.
The if-else
statement is like a toggle switch. You can only
activate one side at a single time, not both. If the logical expression
evaluates to True
, code block 1 is executed and block code
2 is ignored. On the other hand, if the logical expression evaluates to
False
, code block 1 is ignored and code block 2 is
executed.
Let us re-write the code for pass_exam using an if-else
statement:
if-else
def pass_exam(score):
if score >= MINIMUM_PASS:
passed = True
else:
passed = False
return passed
This solution gives the same result for the same logical reason as the
previous version, it just uses an else
.
if-else
Statement
Implement the following function:
def get_parity(num):
"""
-------------------------------------------------------
Determines score is a pass.
Use: parity = get_parity(num)
-------------------------------------------------------
Parameters:
num - a numeric value (int)
Returns:
parity - "Even" if num is evenly divisible by 2, "Odd" otherwise (str)
-------------------------------------------------------
"""
The function docstring tells us that the function determines the parity
of a number and returns a string with value of "Even"
or "Odd"
as appropriate.
Before we start coding we need to think first on how we can determine if an integer is even or odd. In mathematics an integer is even if it is divisible by 2 and is odd if it is not divisible by 2. You already know this from your early school years. The relevant question here is how can we translate 'divisible by 2' into code?
Going back to mathematics, if number X is divisible by Y, then it means
the remainder of dividing X by Y is 0. In Python, the modulo operator %
comes to our rescue. Try writing and testing this function, then look at
the solution:
if-else
Statements
Programs and statements may use multiple if-else
statements.
Implement the following function:
def classify_num(num, divisor):
"""
-------------------------------------------------------
Prints the parity of num and whether it is evenly divisible by divisor.
Use: classify_num(num)
-------------------------------------------------------
Parameters:
num - a numeric value (int)
Returns:
None
-------------------------------------------------------
"""
The function finds the parity of num
and whether it is
divisible by divisor
. The function does not return any
value. Instead, the function prints one of the following messages to the
console:
We have already seen how to find out if a number is even or odd. So, we can borrow that code in our solution. Let us start with:
# check if even or odd
if num % 2 == 0:
print(f"{num} is even")
else:
print(f"{num} is odd")
The only difference to the previous solution is that we replaced the
parity assignment with a print
statement.
Next, we need to add another if-else
statement to find out
if the number is evenly divisible by divisor
:
# check against divisor
if num % divisor == 0:
print(f"and divisible by {divisor}")
else:
print(f"but not divisible by {divisor}")
The final step is to make both print statements work together to produce
a single line. To do that, we need to ensure that the print statement in
the first if-else
block does not end with a new line. This
could be done by adding end=""
at the end of the print
statements. The full solution is:
if-elif
Statements
The if-else
statement supports us with a solution for
scenarios that have an answer of Yes/No. Many real-life scenarios
require answers beyond Yes and No. For instance, a student grade is
normally assigned on a scale of A, B, C, D, and F, rather than a simple
Pass/Fail scheme. To address this issue, Python has the elif
statement for a multi-decision process.
The elif
statement is not a stand-alone command. It is an
extension of the if-else
structure that you learned in the
previous sections. It has the following structure:
if - elif - else
Statement
if <logical expression 1>:
<code block 1>
elif <logical expression 2>:
<code block 2>
...
[elif <logical expression n-1>
<code block n-1>]
[else:
<code block n>]
The above structure allows for multi-decisions without a limit on the
maximum number of decisions. If you want to make n
decisions, you require n
code blocks: one if
statement, n-2
elif statements and one else
statement. The code blocks within the structure are mutually
exclusive: only once of the code blocks within the structure can
possibly be executed. Let us walk through how the interpreter executes
such a structure:
if-elif-else
structure. All other code blocks are ignored.
elif
.
If the evaluation is True, the interpreter executes all lines within
code block 2. When finished, the interpreter jumps to the first line
after the if-elif-else
structure. All other code blocks
are ignored.
elif
and evaluates
it, and so forth.
else
statement will be activated and block n
is executed.
Each of these possible code block executions is called an execution
path. There is only ever one execution path through an if-elif-else
structure. Here is an example:
It is obvious that the test values evaluated must be:
This if-elif-else
covers all the possibilities.
The following code examines a score and returns a string equivalent of the score:
def get_grade(score):
if score <= 100 and score >= 90:
grade = "A"
elif score < 90 and score >= 80:
grade = "B"
elif score < 80 and score >= 65:
grade = "C"
elif score < 65 and score >= 50:
grade = "D"
else:
grade = "F"
return grade
Note that the function does not handle cases where a bad score value (such as -12 or 245) is passed as a parameter. We will examine that in the next section.
Let us trace the program if the value of score is 77. The following lines are evaluated, but the code blocks they define are skipped since none of them evaluate to True if score is 77:
if score <= 100 and score >= 90:
…
elif score < 90 and score >= 80:
…
The following code block is executed:
elif score < 65 and score >= 50:
grade = "D"
and the remaining elif
and else
blocks are
skipped entirely. Again, all of the decision blocks are mutually
exclusive. Only one code block within such a structure can be executed.
Instead the code block:
return grade
is executed since it is the first line of code that follows the if
structure.
We can shorten this code by rewriting it as a fallthrough structure.
We can take advantage of the fact that elif
statements are
executed sequentially. When the code execution of Listing 1 reaches line
7, you are sure that the score is in the range [0,79]. The test in line
5 is False for any value greater than 79, thus there is no way to reach
line 7 if the score is too large. If that is the case, then why bother
to check for a value less than 80 in line 7? That check has already been
done. We can take advantage of these 'shortcuts' and rewrite the
function accordingly:
def get_grade(score):
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 65:
grade = "C"
elif score >= 50:
grade = "D"
else:
grade = "F"
return grade
This is called a fallthrough algorithm. The value being checked
'falls through' the various if
and elif
clauses until it reaches a clause that evaluates to True. Note that this
only works if the logical expressions are in order. The order doesn't
matter in the sense that we could look at scores from 100 down to 0
(descending), or from 0 up to 100 (ascending), but the expressions have
to be in order.
if
Statements
So far, you have seen the if statement, the if-else
statement and the if-elif-else
statement. However, the
discussion is not complete without introducing the concept of nested if
statements.
Nested if statements mean using an if structure inside another if structure. It is like a hierarchy in which you can have multiple layers of if structures within each other.
We used the get_grade function to demonstrate a fallthrough algorithm. What the oroginal code did not do was to verify that the score parameter was a valid grade score. The following code is a re-implementation of the get_grade that uses nested if statements to check for bad parameter values:
def get_grade(score):
if score >= 0 and score <= 100:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 65:
grade = "C"
elif score >= 50:
grade = "D"
else:
grade = "F"
else:
grade = "invalid score"
return grade
In the above solution, the first if-else
structure contains
a nested if-elif-else
structure. The function now checks
for a
score
that is valid, then uses a fallthrough algorithm to determine what the
matching grade is.
Having unnecessary nested if
structures is not a good
programming practice. Below is an example of the bad practice:
def get_grade(score):
if score >= 0 and score <= 100:
if score >= 90:
grade = "A"
else:
if score >= 80:
grade = "B"
else:
if score >= 65:
grade = "C"
else:
if score >= 50:
grade = "D"
else:
grade = "F"
else:
grade = "invalid score"
return grade
Although the function executes exactly like the if-elf-else
version, the use of nested ifs rather than elifs makes the code harder
to read and understand.
If you have got this so far, it means you have now a complete overview
of conditional statements in Python. During your reading, you might be
wondering why we skipped the concept of logical expressions, despite it
being an important component of the conditional statements topic. The
rationale goes back to the observation that some students struggle when
learning about conditional statements if it is mixed with too many
details about logical expressions. Therefore, we decided to move the
discussion to the end when you are comfortable enough with if-else
statements.
The concept of logical expressions and operators were briefly introduced in Lesson 3. The emphasis of Lesson 3, however, was on arithmetic expressions not logical expressions. We are revisiting the topic here because of its strong relevance to conditional statements.
Python, like most languages, has three main logical operators: and
,
or
and not
. These operators work on Boolean
values and produce Boolean results. We will provide a separate
discussion for each operator.
The simplest logical operator is the unary not
operator.
The operator toggles the value of a Boolean variable or literal. If it
is True
, it makes False
, and if it is False
it makes it True
.
Let us see how this works in if-else
statements.
A museum, during the summer season, is offering eight new galleries to its visitors. Tickets sold during the summer season allow non-member guests to access galleries 2 to 6, while members can access galleries 1 as well. If a user has a golden membership, then they have exclusive access to gallery 8, in addition to the other galleries.
Implement the function deny_access()
. The function asks a
user what level of membership they have, then prints a statement
outlining which galleries have been denied access based on their
membership level. The solution:
and
Operator
The logical and
operator returns True
only if
both operands are True
. It evaluates to False
,
if either operand (or both) is False
. We snuck in an
example of using and
with the get_grade function,
as in the line:
and
Sample Usage
def get_grade(score):
if score >= 0 and score <= 100:
…
Line 3 used the and
operator to verify that the
score
parameter was within a valid range. (This could have been written with a
more complex set of nested if statements, but using a logical operator
can simplify code immensely.
It is interesting how logical operators allow us to write code that resembles the English language.
There is a little trick to learn about the and
operator. If
there are multiple operands in a logical expression that uses an and
operator, then it only takes one operand to be False to force the entire
expression to evaluate to False.
For example, Line 3 from above evaluates to False if any condition is False. If it turns out that score is less than zero, Python doesn't even bother to compare score to 100. We call this short-circuit evaluation.
The logical or
operator returns True
if any
operand is True
. It evaluates to False
, only
if both operands are False
. Here is an example:
The or
operator is different than the and operator in some
aspects and is similar in others. Study the following table:
A | B | A and B | A or B |
---|---|---|---|
True |
True |
True |
True |
True |
False |
False |
True |
False |
True |
False |
True |
False |
False |
False |
False |
You can see that both operators produce True
if both
operands are True
, and produce False
if both
operands are False
, but differ in the output if operands
have different values. Therefore, it is inaccurate to think of the
and-or operators as opposites (complements) of each other.
Note that the short-circuit evaluation for the or
operator happens if the interpreter detects any operand with the value True
.
Logical expressions can use a combination of logical operators in a single expression. Some of these expressions are easy to analyze, but others require some analysis to predict the output.
Study the following example:
The study of logical operators is the focus of a discipline in computer science called digital logic design. This is also the title of one of the courses which you will take in your computer science degree. If you like such analysis, you will find the course a joyful experience.
In Lesson 5, you have learned about conditional statements in Python.
You can now read and write conditional statements using if
and if-else
structures. You
have also learned how to expand such expressions using the if-elif-else
structure. In addition, you are now more familiar with logical
expressions and know how to use them in conditional statements.
In this week's assignment, you will get a chance to practice problem-solving using Python. You should be able to recognize that there are multiple approaches to solve the problems, and each approach comes with its own advantages in terms of writability and readability.
In the upcoming lesson, you will carry what you learned here and apply it to a new topic which is the while loops. The topic of while loops is a good bridge between the topic of conditional statements and iterative statements.