Programming for Network Research

Erick Peirson, PhD | | @captbarberousse

Last updated 20 January, 2016

In [1]:
import random    # Ignore me for now!

3. Flow control: if, elif, else, and friends.

In most real-life programming situations, you'll need to do more than a linear set of procedures. Your programs will need to be able to make decisions based on a range of possible conditions. In this notebook we'll talk about how to perform logical operations.

3.1. if and else

The simplest form of decision-making in Python is dichotomous: if some condition is true, then do something; otherwise, do something else. If the weather is nice, then I'll wear sandals; otherwise, I'll wear shoes. If Moe and Curly win the election, I'll move to Norway; otherwise, I'll stay in New York. Notice the pattern: if...then...otherwise. In Python, we can write those kind of instructions almost as I've written the sentences above, using the statements if and else.

In [9]:
x = random.random() # This generates a random float between 0. and 1.

if x < 1./292000000:    # That there's some pretty low odss.
    print 'I won the powerball!'
    print ':-('


if says, "if the following statement is True*, then do the following...". Don't foget the colon (:) afterwards, too. The part after the if statement, print 'I won...., is indented, so that Python knows which part should be conditionally executed.

else says, "otherwise, do this...". Don't forget the colon! else is at the same level of indentation as the if statement, so that Python knows they go together. The part afterward, print ':-(', is indented, so that Python knows it's the part of the code that will get run in the "otherwise" case.

* In Python, the statement need only by "truthy" to be considered True. That is, it could be True, not 0 (or 0.0), or not an empty string.

There are all kinds of comparative operators. For a complete list, see this page.

Here's an example of how to check whether or not a particular item is contained within a list. Say, for example, that I have a list of invitees for a super-secret-underground LAN party, and I want to know if my friend is on the list.

In [15]:
invitees = ['Jack', 'Jane', 'Jim', 'Jill', 'Joseph', 'Jay', 'Josephus']
myfriend = 'Greg'

if myfriend in invitees:
    print 'w00t!'
    print 'l4me'


If I were to win the Powerball AND my friend could come to the LAN party, it would be a pretty great day. I can check for both of those things in one statement, using the and operator.

In [16]:
x = random.random()    # Come on, lucky numbers!

if myfriend in invitees and x < 1./292000000:
    print 'Best day ever!'
    print 'meh.'


Right, pretty unlucky. But I could get over my disappointment if I saw a puppy. So I'll throw in an or operator.

In [17]:
x = random.random()    # I gamble for the thrill.
is_there_a_puppy = True

if (myfriend in invitees and x < 1./292000000) or is_there_a_puppy:
    print "This was much more likely, and I've adjusted my expectations."
    print ':-|'

This was much more likely, and I've adjusted my expectations.

Notice that I threw in some parentheses to group my evaluations. In the example above, the statement

if (myfriend in invitees and x < 1./292000000) or is_there_a_puppy:

evaluates as

if (False and False) or True:

which gets further simplified to

if False or True:

which is just

if True:

3.2. elif

Quite often I want to make a decision that has more than two potential outcomes. Sure, if it's sunny outside I'm down for sandals, otherwise I'd rather wear shoes. But if it's a blizzard, I'm going for snow boots. Consider the elif operator (short for "else if"):

In [20]:
weather = 'blizzard'
footwear = None    # I know that I'm wearing something, but I'm not sure what yet.

if weather == 'sunny':      # ``==`` means "equal to".
    footwear = 'sandals'    # ``=`` means "assign the expression on the right to the variable on the left."
elif weather == 'blizzard':
    footwear = 'snow boots'
    footwear = 'shoes'
print footwear

snow boots

You can use as many elifs as you like!

In [21]:
weather = 'cows'
footwear = None

if weather == 'sunny':
    footwear = 'sandals'
elif weather == 'blizzard':
    footwear = 'snow boots'
elif weather == 'rain':
    footwear = 'galoshes'
elif weather == 'cows':
    footwear = 'run away!'
    footwear = 'shoes'
print footwear

run away!

3.3. Doing things over and over and over.

Sure, my chances of winning the powerball are pretty low for any given draw. The real trick is to play all the time! SOMEONE has to win, right?

This kind of repetitive task calls for a loop. A loop is a control structure in which we do some series of operations repeatedly until some condition is met.

For example, suppose that I have saved up for years and years and now have around $100,000 that I want to gamble away--- er, invest, in the Powerball.

In [49]:
my_life_savings = 100000

while my_life_savings > 0:    # While I still have money in the bank,
    my_life_savings -= 1      # ``-=`` means "subtract one and store the result in the same variable."
                              #  This is the same as writing: my_life_savings = my_life_savings - 1
    x = random.random()       # Wooo!
    if x < 1./292000000:
        print 'JACKPOT!!'

The statement...

while ...:

says: "as long as the following statement (...) is True, do the following thing over and over and over. Unsurprisingly, this is called a "while" loop. In the example above, we decrement (subtract 1) from our life savings every iteration, and stop when there is no money left (my_life_savings <= 0).

Now, in the extremely unlikely case that I win the Powerball, there's really no incentive to keep playing. In that case, I want to stop the loop prematurely. To do that, I use the command break. break will stop the iteration at that very moment.

WARNING WARNING WARNING: avoid endless loops! If you use a while loop, make sure that the condition for the loop (the part that gets evaluated each iteration) will become False in some reasonable duration of time. Consider what would happen if I removed the line that decremented my life savings (my_life_savings -= 1): we'd go on playing the powerball forever! If you do start an endless loop by accident, use the square "stop" button (or select Kernel > Interrupt) in the menu at the top of the notebook.

Here's another case: suppose I have a bunch of measurements about how often individual ants in a colony of Pogonomyrmex barbatus interact with each other.

I sat there with my little notebook for twenty minutes, and counted the number of times each pair of ants touched antennae. Now I have a list of interaction counts, one entry per pair of ants. It's a small colony, only 4 ants, so there are only $4! = 24$ entries.

In [55]:
interactions = [40,  44,  5,  26,  4,  47,  41,  41,  29,  5,  49,  32,    # You can write a list over multiple lines, 
                31,  6,  13,  13,  38,  42,  35,  34,  49,  43,  23,  21]  # just be sure to end the line with a comma.

Now I need to turn those interaction counts into interaction rates, expressed in interactions per minute. I can iterate over the list of interaction counts, perform my math, and store the result in a new list. Notice: my counts are ints, so in order to get a precise result during division I'll need to coerce them into floats.

In [58]:
interaction_frequencies = []    # Make a new, empty list.
for count in interactions:      # Each iteration, I get the next item, and I refer to it as ``count``.
    frequency = float(count)/20.    # Interactions per minute.
    interaction_frequencies.append(frequency)    # ``append()`` adds the value to the end of the list.
print interaction_frequencies

[2.0, 2.2, 0.25, 1.3, 0.2, 2.35, 2.05, 2.05, 1.45, 0.25, 2.45, 1.6, 1.55, 0.3, 0.65, 0.65, 1.9, 2.1, 1.75, 1.7, 2.45, 2.15, 1.15, 1.05]

This is called a for loop (bet you didn't see that coming). Unlike a while loop, which relies on a logical evaluation of some kind, for loops require something to iterate over. We call the thing that we're iterating over the iterator. A list is an iterator: it contains a bunch of elements, and I can get them one at a time.

In [63]:
for number in [0, 1, 2, 3, 4, 5]:
    print number


Strings are also iterators! I can get one character at a time:

In [64]:
for character in 'this string':
    print character


Frequently you will need to perform a task some specific number of times, but not necessarily because you have an iterator of a particular size. For example, suppose I want to calculate $6!$. I know that I will need to perform four multiplication steps ($6*5*4*3*2$). I can use the function xrange to create an iterator over a specified range of integers. For example:

In [66]:
factorial = 6

for i in xrange(1, factorial - 1):    # Yields the ints 1, 2, 3, and 4.
    # ``*=`` means "Multiply this value by the value on the right, and store the result in the same variable.
    factorial *= factorial - i    # The same as: factorial = factorial * (factorial - i)
print factorial



In this notebook you learned about how to add logical and repetitive procedures, using if statements and for and while loops.