6.1. Conditional statements#

6.1.1. If statement#

You may remember that we’ve already seen an example of an if statement in a previous chapter. The syntax of the if statement is as follows:

if expression:
    code block to be executed if the expression is True

Here, expression is a piece of code the evaluates to either the value True or False. Note that the code block must be indented - that tells Python which code is inside the if and which is not.

Here are a few simple examples:

if True:
    print("True is true")   
if True:
    print("The code block")
    print("after 'if' statements")
    print("can have multiple lines.")
if False:
    print("False is not True (this will not be printed)")
if not False:
    print("not False is True")   
if ---:
    print('The expression is true')
a = ---
if a:
    print('The expression is true')
import micropip
await micropip.install("jupyterquiz")
from jupyterquiz import display_quiz
import json

with open("questions3.json", "r") as file:
    questions=json.load(file)
    
display_quiz(questions, border_radius=0)

6.1.2. Comparison and test operators#

In all the examples above, the expression in the if statement was always a value that is either True or False (except for the example of not False). More generally, however, the expression can also include comparisons. Some examples of numerical comparisons are given here:

if 5 == 5:
    print("A double equal sign '==' compares the two sides of itself and gives the")
    print("result 'True' if the two sides have the same value")
a = 5
if a == 5:
    print("== also works with variables")
a = 5
if 5 == a:
    print("The variable can be on either side")
a = 5
b = 5
if a == b:
    print("and == also works with two variables")
a = 5
if a = 5:
    print("This will give an error! A single = is an assignment operator, not a conditional test")
    print("To check if a is equal to 5, you need to use the double equal sign ==")

Warning

Remember the difference between = (assignment operator) and == (equality operator) in Python.

a = 5
if a == 6:
    print("This will not be printed because condition is False.")
a = 5
if 2*a == 10:
    print("You can also use mathematical expressions")    

In addition to the equality operator ==, there are also several other comparison operators such as <, >, >=, <=, !=.

if 5 < 10:
    print('The expression is true')

Python conditional operators

== equal
!= not equal
< less than
<= less than or equal to
> greater than
>= greater than or equal to

import micropip
await micropip.install("jupyterquiz")
from jupyterquiz import display_quiz
import json

with open("questions4.json", "r") as file:
    questions=json.load(file)
    
display_quiz(questions, border_radius=0)

6.1.2.1. Ways to generate True/False#

Boolean True/False may also be given by some other things:

  • Non-Boolean variables can themselves be interpreted as Booleans.
    As we’ve seen above, numerics (float, int) are interpreted as False if they are equal to 0. Lists, tuples, dictionaries, and strings are interpreted as False if they are empty (with nothing inside). None (the null keyword saying something is empty) is interpreted as False. Nearly everything else is interpreted as True.

  • In Python, in checks if an item is contained within a set-like Python type (see example below).
    For instance, x in array_y tests if the value of x is in array_y and returns True if it is. It also works for strings and substrings (so doing 'biol' in 'nanobiology' would return True), and for checking if something is in the keys of a dictionary. The inverse function not in is also valid, but returns the inverse.

  • A command or function can itself return True or False which may be useful for catching errors or exceptions, or more complex behavior (e.g., a function that checks whether or not a simulated cell is touching other cells). More in this in a later chapter on functions.

# Define a list of biomolecules
molecules = ['protein', 'DNA', 'RNA', 'lipid']

# Check if 'lipid' is in the list
if 'lipid' in molecules:
    print("'lipid' is in the list of molecules.")
else:
    print("'lipid' is not in the list of molecules.")
# Your code here

6.1.3. Logical operations#

Python also allows you to build the expression out of logical combinations of several conditions using the logical (Boolean) operators and, or, and not.

Logical operators

and evaluates to True if both conditions are True
or evaluates to True if either condition is True
notevaluates to True if condition is not True

if True and False:
    print("This will not be printed")
if True or False:
    print("This will be printed")
if not 5 > 6:
    print("We have already seen 'not' in previous examples. Here, we also combine with an comparison")
if not 5 != 5:
    print("This is a very silly example (hard to read, bad coding!)")
if 5 < 6 and 10 > 9: 
    print("An example of combining conditional expressions with 'and'")
# Your code here

To understand what happened in part b of this exercise, we have to know whether Python first performs the operation False or True or if it performs the operation not False first.

You can learn about the order in which Python does things in the documentation on operator precedence. In the example above, we can see that the not operator got precedence and Python performed the not before it performed the or.

What if we wanted to have Python perform the or first? You do this by enclosing True or False in brackets:

if not (False or True):
    print("not (False or True) is False so this will not be printed")
import micropip
await micropip.install("jupyterquiz")
from jupyterquiz import display_quiz
import json

with open("questions5.json", "r") as file:
    questions=json.load(file)
    
display_quiz(questions, border_radius=0)

6.1.4. Elif and else statements#

In Python, you can combine the if statement with elif and else commands. This allows you to tell Python what to do in case the starting if statement was False.

elif (standing for “else if”) is a command that allows you to check another condition if the condition of the starting if is False. Note that if the if criterion is True, the elif statement will be skipped and not checked.

else is a command that allows you to execute some code if all of the if and all the elif are False.

if expression_1:
    executed if expression_1 is True
elif expression_2:
    executed if expression_1 is False and expression_2 is True
else:
    executed if both expression_1 and expression_2 are False

Note that to be part of the logical chain, all the elifs and the last else must follow directly after each other’s code blocks with no other code in between. A new if always starts a new chain. You can see how this works in the following examples:

a = 5
if a < 6:
    print("a is less than 6")
else:
    print("a is not less than 6")
a = 5
if a < 6: 
    print("the 'if' statement found that a is less than 6")
elif a < 6:
    print("this will never get printed!")
a = 5
if a < 6: 
    print("the first if found that a is less than 6")
if a < 6:
    print("unlike elif, a second if will get executed.")

Since the code inside your if code block is just regular code, you can also add another if statement inside that code block. This creates a nested if statement inside your first if:

# An example of a nested if statement
a = 4
if a < 6 and a >= 0:
    if a > 3:
        print("the value of a is 4 or 5")
    else:
        print("the value of a is 0, 1, 2, or 3")
else:
    print("none of these are the case")

Notice that indendation matters also in nested statements!

import micropip
await micropip.install("jupyterquiz")
from jupyterquiz import display_quiz
import json

with open("questions6.json", "r") as file:
    questions=json.load(file)
    
display_quiz(questions, border_radius=0)

6.1.5. (Optional) The match case statement#

In addition to if-elif-else, there is also the match case conditional statement, in which we first pass a parameter to match and then check with which case the parameter is satisfied. If a match is found, the corresponding code block is executed. If no match is found, a default action will take place; in syntax, this is denoted with the _ wildcard character.

The match case conditional statement follows this syntax:

match parameter:
    case pattern1:
        code block for pattern1
    case pattern2:
        code block for pattern2
    ...
    case patterN:
        code block for patternN
    case _:
        default code block

Let’s check out a simple example. Copy-paste code blocks below to your VS Code to run them, because input is buggy in the Jupyter book.

# Ask user input
number = int(input("Enter an integer number between 1 and 3: "))

# Inform user which number was inputed
match number:
        case 1:
            print("One")
        case 2:
            print("Two")
        case 3:
            print("Three")
        case _:
            print("Number not between 1 and 3")

Just as in if-elif-else, it’s also possible to use logical operators (such as | for OR) in match-case. Moreover, we can use if within match-case.

# Ask user input
number = int(input("Enter an integer number between 1 and 3: "))

# Inform user which number was inputed
match number:
        case 1 | 2:
            print("One or Two")
        case 3:
            print("Three")
        case _:
            print("Number not between 1 and 3")
# Ask user input
number = int(input("Enter an integer number: "))

# Inform user whether the inputed number is positive, negative, or zero
match number:
        case number if number > 0:
            print("Positive")
        case number if number < 0:
            print("Negative")
        case _:
            print("Zero")

For more examples how to use match-case, check out this website.

Usage of if-elif-else and match-case

When should we use if-elif-else, and when match-case?

if-elif-else is more straightforward for simple condition checks, Boolean expressions, or when you need to perform comparisons between variables or evaluate more complex logic. On the other hand, match-case is more concise in complex scenarios, so you can use it to match against complex patterns or when you need a clear and concise way to handle multiple literal cases. In this context, “literal cases” refers to specific, concrete values or conditions that you want to match directly, without needing any complex logic or expressions.