An introduction to solving biological problems with Python

Session 2.1: Conditional execution

Program control and logic

A program will normally run by executing the stated commands, one after the other in sequential order. Frequently however, you will need the program to deviate from this. There are several ways of diverting from the line-by-line paradigm:

  • With conditional statements. Here you can check if some statement or expression is true, and if it is then you continue on with the following block of code, otherwise you might skip it or execute a different bit of code.

  • By performing repetitive loops through the same block of code, where each time through the loop different values may be used for the variables.

  • Through the use of functions (subroutines) where the program’s execution jumps from a particular line of code to an entirely different spot, even in a different file or module, to do a task before (usually) jumping back again. Functions are covered in the next session, so we will not discuss them yet.

  • By checking if an error or exception occurs, i.e. something illegal has happened, and executing different blocks of code accordingly

Code blocks

With all of the means by which Python code execution can jump about we naturally need to be aware of the boundaries of the block of code we jump into, so that it is clear at what point the job is done, and program execution can jump back again. In essence it is required that the end of a function, loop or conditional statement be defined, so that we know the bounds of their respective code blocks.

Python uses indentation to show which statements are in a block of code, other languages use specific begin and end statements or curly braces {}. It doesn't matter how much indentation you use, but the whole block must be consistent, i.e., if the first statement is indented by four spaces, the rest of the block must be indented by the same amount. The Python style guide recommends using 4-space indentation. Use spaces, rather than tabs, since different editors display tab characters with different widths.

The use of indentation to delineate code blocks is illustrated in an abstract manner in the following scheme:

Statement 1:

Command A – in the block of statement 1
Command B – in the block of statement 1

Statement 2:
    Command C – in the block of statement 2
    Command D – in the block of statement 2

Command E – back in the block of statement 1

Command F – outside all statement blocks

Conditional execution

The if statement

A conditional if statement is used to specify that some block of code should only be executed if some associated test is upheld; a conditional expression evaluates to True. This might also involve subsidiary checks using the elif statement to use an alternative block if the previous expression turns out to be False. There can even be a final else statement to do something if none of the checks are passed.

The following uses statements that test whether a number is less than zero, greater than zero or otherwise equal to zero and will print out a different message in each case:


In [ ]:
x = -3

if x > 0:
  print("Value is positive")

elif x < 0:
  print("Value is negative")

else:
  print("Value is zero")

The general form of writing out such combined conditional statements is as follows:

if conditionalExpression1:
    # codeBlock1

elif conditionalExpression2:
    # codeBlock2

elif conditionalExpressionN:
    # codeBlockN
    +any number of additional elif statements, then finally:

else:
    # codeBlockE

The elif block is optional, and we can use as many as we like. The else block is also optional, so will only have the if statement, which is a fairly common situation. It is often good practice to include else where possible though, so that you always catch cases that do not pass, otherwise values might go unnoticed, which might not be the desired behaviour.

Placeholders are needed for “empty” code blocks:


In [ ]:
gene = "BRCA2"
geneExpression = -1.2

if geneExpression < 0:
    print(gene, "is downregulated")
        
elif geneExpression > 0:
    print(gene, "is upregulated")
        
else:
    pass

For very simple conditional checks, you can write the if statement on a single line as a single expression, and the result will be the expression before the if if the condition is true or the expression after the else otherwise.


In [ ]:
x = 11

if x < 10:
    s = "Yes"
else:
    s = "No"
print(s)

# Could also be written onto one line
s = "Yes" if x < 10 else "No"
print(s)

Comparisons and truth

With conditional execution the question naturally arises as to which expressions are deemed to be true and which false. For the python boolean values True and False the answer is (hopefully) obvious. Also, the logical states of truth and falsehood that result from conditional checks like “Is x greater than 5?” or “Is y in this list?” are also clear. When comparing values Python has the standard comparison (or relational) operators, some of which we have already seen:

Operator Description Example
== equality 1 == 2 # False
!= non equality 1 != 2 # True
< less than 1 < 2 # True
<= equal or less than 2 <= 2 # True
> greater then 1 > 2 # False
>= equal or greater than 1 >= 1 # True

It is notable that comparison operations can be combined, for example to check if a value is within a range.


In [ ]:
x = -5

if x > 0 and x < 10:
    print("In range A")
    
elif x < 0 or x > 10:
    print("In range B")

Python has two additional comparison operators is and is not.

These compare whether two objects are the same object, whereas == and != compare whether values are the same.

There is a simple rule of thumb to tell when to use == or is:

  • == is for value equality. Use it to check if two objects have the same value.
  • is is for reference equality. Use it to check if two references refer to the same object.

Something to note, you will get unexpected and inconsistent results if you mistakenly use is to compare for reference equality on integers:


In [ ]:
a = 500
b = 500
print(a == b) # True
print(a is b) # False

Another example with lists x, y, and z:

  • y being a copy of x
  • and z being another reference to the same object as x

In [ ]:
x = [123, 54, 92, 87, 33]
y = x[:] # y is a copy of x
z = x
print(x)
print(y)
print(z)
print("Are values of y and x the same?", y == x)
print("Are objects y and x the same?", y is x)
print("Are values of z and x the same?", z == x)
print("Are objects z and x the same?", z is x)

In [ ]:
# Let's change x
x[1] = 23
print(x)
print(y)
print(z)
print("Are values of y and x the same?", y == x)
print("Are objects y and x the same?", y is x)
print("Are values of z and x the same?", z == x)
print("Are objects z and x the same?", z is x)

In Python even expressions that do not involve an obvious boolean value can be assigned a status of "truthfulness"; the value of an item itself can be forced to be considered as either True or False inside an if statement. For the Python built-in types discussed in this chapter the following are deemed to be False in such a context:

False value Description
None numeric equality
False False boolean
0 0 integer
0.0 0.0 floating point
"" empty string
() empty tuple
[] empty list
{} empty dictonary
set() empty set

And everything else is deemed to be True in a conditional context.


In [ ]:
x = ''      # An empty string
y = ['a']   # A list with one item

if x:
    print("x is true")
else: 
    print("x is false")     

if y:
    print("y is true")
else:
    print("y is false")

Exercises 2.1.1

Create a if..elif..else block that will compare a variable containing your age to another variable containing another person's age and print a statement which says if you are younger, older or the same age as that person.

Exercises 2.1.2

Use an if statement to check if some variable containing DNA sequence contains a stop codon. (e.g. dna = "ATGGCGGTCGAATAG"), first just check for one possible stop, but then extend your code to look for any of the 3 stop codons (TAG, TAA, TGA). Hint: recall that the in operator lets you check if a string contains some substring, and returns True or False accordingly.

Next session

Go to our next notebook: python_basic_2_2