Python Conditional Statements

Chapter 18 16 mins

Learning outcomes:

  1. The if and else statements
  2. The elif statement
  3. Using logical operators or, and and not
  4. Nesting if statements

Introduction

Back in the Python Basics — Control Flow chapter, we learnt about the if and else keywords, how to set up if statements and so on.

In this chapter, we shall see in detail how to set up if statements along with elif statements; how to nest if statements execute blocks of code based on the truth of multiple conditions; and much more.

Let's begin!

The if and else statements

We'll start by reviewing the syntax of the if statement.

if condition:
    # code to be executed if condition is True

The if statement executes a block of code when a given condition turns out to be true. This condition is written in the form of a Boolean.

If the Boolean is True, the block of code is executed. Similarly, if it's False, the block is ignored. In the latter case, execution moves to the else statement, if provided.

Shown below is the syntax of the else statement:

if condition:
    # code to be executed if condition is True
else:
    # code to be executed if condition is False

If the given condition is False, execution shifts to the else block.

A couple of examples utilising the if and else statements are demonstrated below.

Check whether a given integer a is divisible by 9. If it is, then print the quotient, as an integer, when 9 divides that number.

Assume the following code has been set up:

a = 50

To check for divisibility by 9 we have to use the % modulus operator. It returns the remainder when an integer is divided by another integer. In this case, we need to check for a remainder of 0 — which implies divisibility.

a = 50

if a % 9 == 0:
    print(a // 9)

Keep in mind that the printed quotient needs to be an integer. Therefore we use the // floor division operator to return an integer from the division.

Check whether two given strings s1 and s2 are equal to one another and print 'Yes' if they are, or else 'No'.

Assume the following code has been set up:

s1 = input("String 1: ")
s2 = input("String 2: ")

To check for the equality of two strings we can use the = equality operator. It returns True if both its operands are equal to one another, and False otherwise.

s1 = input("String 1: ")
s2 = input("String 2: ")

if s1 == s2:
    print('Yes')
else:
    print('No')

The elif statement

More than often, it's desired to check for other conditions once we get to know that a given condition turned out to be false. This can be achieved by putting an if statement inside an else statement.

if condition1:
    # code to execute if condition1 is True
else:
    if condition2:
        # code to execute if condition2 is True
    else:
        # code to execute if both condition1 and condition2 are False

If the if statement fails, the following else block takes over. Inside the else block, another condition is tested; if it fails then its else block takes over and so on and so forth.

As you would agree, this syntax can become quite tedious once the number of conditions to check increases.

Fortunately, Python provides an easier syntax to check for another condition if one fails. That is using the elif statement.

if condition1:
    # code to execute if condition1 is True
elif condition2:
    # code to execute if condition1 is False, and condition2 is True
else:
    # code to execute if both condition1 and condition2 are False

First of all, 'elif' stands for 'else if' which simply comes from the idea of a nested if statement inside an else statement, as we've seen above.

Secondly, the syntax of elif resembles that of an if statement — the elif keyword followed by the condition to check, followed by a colon, followed by the block of code to be executed if the condition evaluates to True.

One thing apparent in the code above is that, just like an else statement, an elif statement can't appear on its own — it has to have a preceding if statement.

Below shown are a couple of cases where elif is useful.

Print '2' if a given integer a is divisible by 2, or '3' if it is divisible by 3, or 'None' if it's not divisible by any one.

Assume the following code has been set up:

a = 12

To check for the equality of two strings we can use the = equality operator. It returns True if both its operands are equal to one another, and False otherwise.

a = 12

if a % 2 == 0:
    print('2')
elif a % 3 == 0:
    print('3')
else:
    print('None')

Using logical operators

Most of the times when working with the if family of statements, it's desired to combine multiple conditions and execute code based on the fact whether some, or all, or none of them are true.

Although this can be accomplished solely using if, elif and else, it's useless and inefficient.

It's rather recommended to use logical operators in such cases, to connect multiple conditions together in a much more compact way.

Below we explore all the three logical operators — or, and and not — along with an explanation of when to use them.

The or operator

If you need to perform the same action if either of two given conditions are met, then it would be inefficient to use elif to do so.

For instance, say you want to print 'Divisible' if the user enters a number that is divisible either by 2 or 3.

Doing so using an if and elif statement would look something like this:

num = 7

if num % 2 == 0:
    print('Divisible')

elif num % 3 == 0:
    print('Divisible')

See how the print() statement is repeated twice.

It's only when the action for each of a list of conditions is different than that of another, that the if..elif statement sounds sensible.

If the action for two or more conditions' fulfillment is the same, then it's much more efficient to use the logical or operator.

Recall that the or operator returns True if either of its operators evaluates to True.

Using or, the problem above can be solved much more neatly as follows:

num = 7

if num % 2 == 0 or num % 3 == 0:
    print('Divisible')

The expression in line 3 would evaluate to True if either num % 2 == 0 is True or num % 3 == 0 is True, or both are True. And if this is the case, the if's block would be executed.

There's only one scenario where the if statement won't be executed. That is when both the given conditions evaluate to False.

See how much similar is the statement above to plain English: if num is divisible by 2 or 3, then print 'Divisible'.

A more practical-level example of where could or be used is illustrated below.

Write some code to construct a 3 x 3 matrix, that has all 1's in the first row and the first column, and 0 otherwise.

The following code has been set up for the matrix:

matrix = []

for i in range(3):
    matrix.append([])
    for j in range(3):
        # your code goes here
matrix = []

for i in range(3):
    matrix.append([])
    for j in range(3):
        if i == 0 or j == 0:
            matrix[i].append(1)
        else:
            matrix[i].append(0)

The and operator

Sometimes, instead of checking for the truth of at least one condition in a list of multiple conditions as we did above, it's required to check the truth of all the conditions.

That is, we want to see whether all of them are fulfilled and only then execute a piece of code.

Suppose we want to print 'Not divisible by 6' if a number num is not divisible by both 2 and 3.

Using the usual if and else statements, this can be accomplished as follows:

num = 7

if num % 2 != 0:
    if num % 3 != 0:
        print('Not divisible by 6')

If num is not divisible by 2, then it's further checked if it's also not divisible by 3. If this is so, 'Not divisible by 6' is printed.

As before, checking for the truth of multiple conditions using multiple if statements is inefficient — we have to write multiple if statements in increased level of indentations which compromises code readability.

A much better way is to use the logical and operator.

The and operator returns True if both of its operands evaluates to True, and False otherwise.

Let's rewrite the code above using and:

num = 7

if num % 2 != 0 and num != 3 == 0:
    print('Not divisible by 6')

Once again, see how similar the if statement sounds to normal English: if num is not divisible by 2 and by 3, then print 'Not divisible by 6'.

Given two numbers a and b, check whether both of them are positive, and if they are, then print their sum.

The following code has been set up:

a = 10
b = 20

# your code goes here
a = 10
b = 20

if a > 0 and b > 0:
    print(a + b)

The not operator

Performing an operation when a given condition is False is another common routine in conditional programming.

For example, a signin form may show an error message if the entered credentials do not correspond to an account; or an online email marketing tool may block certain features if the user it not on a premium plan and so on.

In short, the use cases where the negation of a given condition is required to be True are endless.

In such cases, it's really handy to use the logical not operator.

Let's say we have an image editing software with two plans: premium and free. The premium one offers many tools, whereas the free version has them disabled.

In a real-world scenario, we would check whether the user's version is premium, and then enable all the cool features. However, for now, we can emulate this whole idea using a Boolean variable and a single if conditional.

The variable is_premium specifies whether the current software is premium or not. What we want to do is print 'Not premium' if the current software's version is not premium i.e is_premium is False.

One way to do so is to check for the equality of is_premium with False:

if is_premium == False:
    print('Not premium')

However, this doesn't sound native.

A better sounding code is shown below, utilising the not operator:

if not is_premium:
    print('Not premium')

See how natural it sounds: if the plan is not premium, print 'Not premium'.

Nesting if statements

The operators and, or and not, sure simplify many conditional execution concerns. However, they aren't well-suited to all such concerns.

Sometimes, the best choice is to nest conditional statements within themselves to achieve the desired flow of execution.

In particular, when the action to be made on the fulfillment of each set of conditions is different, it's useless to use the logical operators shown above.

An example is illustrated below:

We need to print 'Divisible by 4' if a given number num is divisible by 4, or 'Divisible by 2 only' if it's divisible by 2.

num = 10

if num % 4 == 0:
    print('Divisible by 4')

elif num % 2 == 0:
    print('Divisible by 2 only')

First, it's checked whether num is divisible by 4. If it is, we make the desired output. However, if it is not, then we check if it's rather divisible by 2. If this is the case, we make the desired output.

When working with nested if statements, make sure you correctly place all the indentations and that the overall conditional block (including the nestings) achieves what you desire to.

Let's take another example:

If a number num is divisible by 2 we print 'Divisible by 2'. Further more, we check if it's divisible by 4. If it is, we print 'Divisible by 4'.

If it's not divisible by 4, we print 'Not divisible by 4'. And similarly, if it's not divisible by 2, we print 'Not divisible by 2'.

Here's the code:

num = 6

if num % 2 == 0:
    print('Divisible by 2')

    if num % 4 == 0:
        print('Divisible by 4')
    else:
        print('Not divisible by 4')

else:
    print('Not divisible by 2')
Divisible by 2
Not divisible by 4

If num is not divisible by 2, there's no point of further checking for divisibility by 4. It's known that the number isn't divisible by 4. This follows from the elementary laws of arithmetic and divisibility.

Likewise, in the else statement in line 11, we just print 'Not divisible by 2'. There is no need to put a check for divisibility by 4.