Up to now, the short scripts we’ve written have been simple linear sequences of commands we want Python to execute.
While some simple tasks won’t go beyond this format, most scripts and programs use conditional execution and looping to achieve their tasks.
if...else
Many computational tasks require us to conditionally perform some operations, or where the computation forks depending on the value of some variable.
For example, we might have a calculation that at some point generates a distance.
We then want to print the distance in a nice human readable format; if the distance is 0.0001 m we might prefer it to read “0.1 mm”, while if the distance is 32000 m printing “20 miles” would be more useful.
As with most programming languages, this conditional execution is achieved
through use of an if
-else
statement.
For example,
# Somewhere in a chunk of code, we have calculated a distance in meters
# which we store in variable "dist"
print(dist) # This would print 0.0001 or 32000 in the two cases above
if (dist < 0.1):
print("Which is " + str( dist * 1000 ) + " mm")
elif( dist > 1609 ):
print("Which is " + str( dist / 1609 ) + " miles")
else:
print("Which is " + str(dist) + " meters")
Here we’ve shown the three possible parts of an if
block; the if
part will always
be present, while the elif
and else
are optional.
The syntax is:
if <STATEMENT THAT EVALUATES TO TRUE OR FALSE> :
# Stuff to do if it's true
elif <ANOTHER STATEMENT THAT EVALUATES TO TRUE OR FALSE>: # OPTIONAL
# Stuff to do if the `if` part was False but this part is True
else: # OPTIONAL
# Stuff to do if all previous if/elifs were False.
As mentioned at the end of the first section, the indentation above is not accidental!
Python uses indentation to demarcate logical blocks.
In this case, everything after the
if
statement that is indented is inside the if
block.
Returning to the previous level of indentation signals the end of the if
block.
The elif
and else
are the only exceptions in this case, as they are logical
extensions to the if
block.
To further illustrate this consider the following code;
if a < 5:
print("Ya")
print("Hoo")
This section of code will always print Hoo
(irrespective of the value contained in a
) and only print Ya
if a
is less than 5.
On the other hand
if a < 5:
print("Ya")
print("Hoo")
will only print Ya
followed by Hoo
(if a
is less than 5) or nothing (if a
is more than or equal to 5).
Changing just the indentation level of the second print statement, has determined whether it is part of the if
block or not.
Other languages
If you’ve learnt C,C++, or Java, then indentation is roughly the same as curly brackets in those languages. For example the last snippet of code in Java would be written as
if( a<5 ){ System.out.println("Ya"); System.out.println("Hoo"); }
(where in Java the indentation is optional!)
for
-in
To really start to benefit from having a computer do things for us, we often need it to do almost the same thing repeatedly, with only small changes between each time it repeats.
For example, we might want to batch process a directory full of data files, in which case we change only the filename between each run and the program treats each file in the same way.
We might be iterating over a set of time series and applying the same filters and analyses to each one.
Or on an even finer-scale level, most image processing algorithms work by, at some point, looping over all the pixels in an image and performing the same operation at each location.
Whatever the level of processing, these scenarios all have one
thing in common; they’re achieved by using loops. In most cases,
we would choose a for
loop, which is a way of iterating over
a set list of elements (files, line-series, pixels). In
most languages, we have to explicitly change the base object
of each iteration, usually by indexing into a list.
This can also be done with Python. For example
l = ["a","b","c","d","e"]
for i in range(len(l)):
print(l[i])
outputs:
a
b
c
d
e
Here,
for
loop over the list of index values generated by range
, 0-4print
the value of the list at the index valuei
is usually referred to as the loop variable as it’s the thing that
changes between each invocation of the code inside the loop.
So in each iteration of the loop, i
takes on a value (from 0 to 4) and
we use that value to index the original list l
, and print the item
in the list (letter) at index i
.
However, in Python, instead of having to loop over indices, we can loop over the items we’re interested in themselves directly;
l = ["a","b","c","d","e"]
for c in l:
print(c)
outputs:
a
b
c
d
e
While we haven’t saved any lines of code (yet!), the syntax has become much more readable.
Loosely translated:
for c in l:
is the same as for each item in l that we’ll call c.
As shown above, we can still use indecies if we prefer.
enumerate
Python even provides a convenience function, called enumerate
, that
returns both an index and a value for each item in a sequence:
l = ["a","b","c","d","e"]
for i,c in enumerate(l):
print("At index ", i, "the item is ", c)
outputs:
At index 0 the item is a
At index 1 the item is b
At index 2 the item is c
At index 3 the item is d
At index 4 the item is e
Write a script (name the file exercise_loops.py
)
that creates a list of the numbers 0 to 49 inclusive (0, 1, .., 49),
and then prints out for each one whether it is odd or even.
Use a for
loop containing an if
-else
block.
Other than that, you can check whether a number is odd or even by using the modulo operator % (= remainder of division) with modulo 2:
x%2
The result is 0 for even numbers and 1 for odd numbers.
This can be achieved as follows
# generate a list of numbers from 0 to 49 inclusive
numbers = list(range(50))
for n in numbers:
# Check if the number is odd or even by checking modulo 2...
if n%2:
print(n, "is odd")
else:
print(n, "is even")
to give
0 is even
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even
11 is odd
12 is even
13 is odd
14 is even
15 is odd
16 is even
17 is odd
18 is even
19 is odd
20 is even
21 is odd
22 is even
23 is odd
24 is even
25 is odd
26 is even
27 is odd
28 is even
29 is odd
30 is even
31 is odd
32 is even
33 is odd
34 is even
35 is odd
36 is even
37 is odd
38 is even
39 is odd
40 is even
41 is odd
42 is even
43 is odd
44 is even
45 is odd
46 is even
47 is odd
48 is even
49 is odd
while
There is another looping mechanism we can use instead of the for
loop, called a while
loop.
while
loops are mainly used when the exact number of times we
want to repeat something is not known before starting the loop.
For things like pixels and files in a directory, we would usually
use for
loops as we know before starting the loop how many files
there are or how many pixels there are.
But if we had an optimization algorithm, such algorithms usually continue
until a desired closeness to an ideal solution has been found (or a
maximum number of tries has been reached).
As writing optimization algorithms is difficult, we’re going to simulate one using the random number module instead.
For example
import random # This imports the random number module
n = 1
tries = 0
while n > 0.1:
n = random.random() # This generates a random number between 0 and 1
tries += 1
print("It took", tries, "tries to roll a random number less than 0.1, =", n)
A typical output from this would be
It took 3 tries to roll a random number less than 0.1, = 0.07209438256934753
So what’s happening here?
After importing the random module (more on this in the next section!), we start with two variables,
n
for the random number, and tries
to
hold the number of times we’ve tried.
We set n
to 1 so that the while
loop will be executed at least once
(otherwise if e.g. n
starts at 0, then the while
condition will
immediately be False
and the loop would never be entered!), and tries
to 0.
Then, inside the while
loop, we generate a new value for the random number,
and increase tries
by 1.
As we then come to the end of the body of the while
block, the condition
gets tested again - is n
still more than 0.1 or not? If so, go again.
And so on until n
is less than (or equal to) 0.1.
Once n
is less than or equal to 0.1, the comparison n > 0.1
returns
False
, and the while
loop stops.
Then we proceed to the next line and print the text and values.
Can you guess what would happen if we removed the line that
generates a new random value for n
?
If you’re not sure, work through the snippet line by line and see if you can figure it out.
If you’re still not sure, ask a demonstrator.
Write a script (name the file exercise_while.py
)
that determines how many squares (startng with the
sequence 12 = 1,
22 = 4, 32 = 9, etc) are needed,
such that their sum exceeds 1,000,000.
Have the script print out the number of squares needed and their sum (which should exceed 1,000,000!).
i = 1
summ = 1
while summ <= 1E6:
i += 1
summ += i**2
print(i, "squares needed to exceed 1E6 - up to", summ)
Should produce
144 squares needed to exceed 1E6 - up to 1005720