4. Basic Programming Techniques¶
In this section we cover the main branching and looping methods in Python. We use loops if we have codes that needs to get repeated. We use branching if we want to evaluate alternative parts of our codes depending on a runtime condition.
4.1. Branching into Alternative Code Blocks¶
4.1.1. The if statment¶
The if
command can be used to check whether a certain condition is true. If
it is true, then we can assign a certain chain of commands (i.e., a block of
code) for this
eventuality. If, on the other hand, the condition in the if
statement is
wrong, we can branch off our program into another direction and assign
different commands (i.e., an alternative code block). This allows us to branch our
program into two (or more) separate possible directions.
In Python it is very important to get the “indentation” right. So all the
commands that we want to be executed after the if
statement need to be “indented”
by 4 spaces (just hit the tab-key on your keyboard once). Python does not use the curly
brackets {}
that R, Stata, Java, C or other programming languages use in
their versions of the if-statements and for-loops.
Here is a simple example of an if
statement that is used to branch the code
into two alternate routes depending on the value stored in variable x
. You
can read the if
statement below as “if the value of x is larger than one
half, then do one thing. If it is not, then do the other thing.”
x = 2
if (x > 0.5):
print("Number x= {} is greater than 0.5".format(x))
else:
print("Number x= {} is smaller than or equal to 0.5".format(x))
Number x= 2 is greater than 0.5
We next branch the program into 3 separate directions depending on 3 mutually exclusive conditions.
x = 2
y = 4
if (x > y):
print("X is greater than Y")
elif (x==y):
print("X is equal to Y")
elif (x < y):
print("X is smaller than Y")
X is smaller than Y
Warning
Note the double equal symbol ==
. This is a logical operator or
a Boolean operator such as EQUAL, AND, OR, and NOT. While the single equal
symbol =
is an assignment operator (i.e., x = 3
assigns the value 3
to variable with name x
), the double equal symbol is a logical operator.
You can find more information about Boolean operators here: Wiki-Boolean
Operators
The expression x == 3
for instance asks whether the content of variable
x
equals the value of 3. If it does, the statement returns True
and
if it does not, the statement returns False
.
In the field of Logic the state of True
is often coded with the value
1
and the state of False
is coded as the value 0
. When you used
dummy variables in econometrics you basically used a Boolean variable. A
dummy variable is simply an indicator variable taking the value 0 or 1 to
indicate whether a certain observation belongs to a specific category.
Here is an example to illustrate the difference between =
and ==
.
# Assign value 3 to variable with name x using singe equal symbol
x = 3
print(x)
# Check whether the value of variable x is 3?
print(x == 3)
# Check whether the value of variable x is 4?
print(x == 4)
3
True
False
The elif (x==y)
statement above checks whether the value of variable x
is equal to the value of variable y
at that particular point in your code
(i.e., at runtime). If this is the case, the elif
function returns the
value 1
(which means True
) and then executes the associated code block.
Here is another simple example using a branching if
statement. We
first draw some random number between 0 and 1 using the random()
function.
In order to use this function we first have to import the library in which this
function is stored as it is not part of the core functions. We again use the
import
statement to import the random
library. One of the functions in
the random
library is the function random()
(yes it has the same name
but there are other functions in the random
library as well). In order to
call the function random()
we need to indicate the library name followed by
a .
(dot) and then the function name. So all in all this is:
random.random()
which will draw a random number between 0 and 1.
We then check whether the number is smaller or larger than 0.5. For each
eventuality we can then assign a string of commands to be executed.
import random
x = random.random()
if (x > 0.5):
print("Random Number x= {:5.2f} is greater than 0.5".format(x))
else:
print("Random Number x= {:5.2f} is smaller than or equal to 0.5".format(x))
Random Number x= 0.07 is smaller than or equal to 0.5
We can also ask for more than one branching criteria again such as
import random
x = random.random()
if (x > 0.9):
print("Random Number x= {:5.2f} is greater than 0.9".format(x))
elif (x > 0.8):
print("Random Number x= {:5.2f} is greater than 0.8".format(x))
elif (x > 0.7):
print("Random Number x= {:5.2f} is greater than 0.7".format(x))
else:
print("Random Number x= {:5.2f} is smaller than or equal to 0.7".format(x))
Random Number x= 0.96 is greater than 0.9
Running the same script again, will result in a different random number being drawn, so that the result may differ of course.
import random
x = random.random()
if (x > 0.9):
print("Random Number x= {:5.2f} is greater than 0.9".format(x))
elif (x > 0.8):
print("Random Number x= {:5.2f} is greater than 0.8".format(x))
elif (x > 0.7):
print("Random Number x= {:5.2f} is greater than 0.7".format(x))
else:
print("Random Number x= {:5.2f} is smaller than or equal to 0.7".format(x))
Random Number x= 0.07 is smaller than or equal to 0.7
4.1.2. Branching with Logical Operators¶
Finally, we can use logical operators such as and
as well as or
to
construct more sophisticated conditions for code branching. Assume, for
instance, that you program a game that assigns a price of $1 if a random number
is greater than 0.3 but less than 0.5. You could use the logical statement
and
to accomplish this as follows:
import random
x = random.random()
print("Random Number is x= {:5.2f}".format(x))
if (x > 0.3 and x < 0.5):
print("You win a price of $1, congratulations!")
else:
print("Sorry, you win nothing!")
Random Number is x= 0.93
Sorry, you win nothing!
A different game could assign a price of $1 to a player if a randomly drawn
number is less than 0.3 or greater than 0.5. If you want to program this game,
you would use the logical operator or
as:
import random
x = random.random()
print("Random Number is x= {:5.2f}".format(x))
if (x < 0.3 or x > 0.5):
print("You win a price of $1, congratulations!")
else:
print("Sorry, you win nothing!")
Random Number is x= 0.73
You win a price of $1, congratulations!
And you can of course combine these as well. A more complex game could pay the
player $1 if the random number is at least 0.1 but less than two 0.2 or larger
than 0.6. Notice that “at least 0.1” means that 0.1 is included in the
condition so you need the >=
symbol as opposed the strictly greater >
.
You could program this as:
import random
x = random.random()
print("Random Number is x= {:5.2f}".format(x))
if (x >= 0.1 and x < 0.2) or (x > 0.6):
print("You win a price of $1, congratulations!")
else:
print("Sorry, you win nothing!")
Random Number is x= 0.96
You win a price of $1, congratulations!
4.2. For-Loops¶
4.2.1. Loop to Repeat a Simple Print Function¶
Assume you have the following assignment. Please print the following on a screen:
i = 0
i = 1
i = 2
i = 3
etc.
i = 9
We could first of course just write simple print statements as follows:
print('i = {}'.format(0))
print('i = {}'.format(1))
print('i = {}'.format(2))
print('i = {}'.format(3))
print('i = {}'.format(4))
print('i = {}'.format(5))
print('i = {}'.format(6))
print('i = {}'.format(7))
print('i = {}'.format(8))
print('i = {}'.format(9))
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
Not wrong, but pretty slow to produce and boring. Whenever a task is repetitive and boring there is probably a quicker and more exciting way of accomplishing it.
Let’s think about a loop implementation. Try this:
for i in range(10):
print('i = {}'.format(i))
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
Note that we again need to increment the print statement inside of the loop
with 4! white-spaces.
The range()
command will generate a list with 10
objects in it. The
objects are the numbers from [0,1,...9]
. It will then
instruct the computer to assign the list elements to variable i
in each
round.
You can then decide what to do with the specific value of
variable i
in each round.
Variable i
is called the iterator or counter as it changes its value in
every iteration of the loop and in a way counts in which round you currently
are. Here’s a more elaborate example.
for i in range(10):
x = i/2
print('Round: {}'.format(i))
print('------------------------')
print('i = {}'.format(i))
print('x = i/2 = {}/2 = {}'.format(i, x))
print('------------------------')
Round: 0
------------------------
i = 0
x = i/2 = 0/2 = 0.0
------------------------
Round: 1
------------------------
i = 1
x = i/2 = 1/2 = 0.5
------------------------
Round: 2
------------------------
i = 2
x = i/2 = 2/2 = 1.0
------------------------
Round: 3
------------------------
i = 3
x = i/2 = 3/2 = 1.5
------------------------
Round: 4
------------------------
i = 4
x = i/2 = 4/2 = 2.0
------------------------
Round: 5
------------------------
i = 5
x = i/2 = 5/2 = 2.5
------------------------
Round: 6
------------------------
i = 6
x = i/2 = 6/2 = 3.0
------------------------
Round: 7
------------------------
i = 7
x = i/2 = 7/2 = 3.5
------------------------
Round: 8
------------------------
i = 8
x = i/2 = 8/2 = 4.0
------------------------
Round: 9
------------------------
i = 9
x = i/2 = 9/2 = 4.5
------------------------
4.2.2. Loop to Calculate the Sum of Numbers¶
Here is another simple example. We first assign a list with values 0,1,2,3,4,5.
We then “loop” through all the values of this list and print them one by one.
In addition, we add up all the values of this list. The command
for x in range(6)
assigns x
equal to each value of 0,1, ...,5
one
by one and we can then use x
itself in each iteration.
Note that if you want a list from 0,1,…,5 you need to define the range
command with range(6)
. Using this loop we can step through all the values of our
list and assign certain operations to each value.
# Summation variable starting with zero value
sumx = 0
# Start loop
for x in range(6):
sumx = sumx + x # adds up the elements from 0 to 5
print("x = {}".format(x))
print("sum(x) = {}".format(sumx))
x = 0
sum(x) = 0
x = 1
sum(x) = 1
x = 2
sum(x) = 3
x = 3
sum(x) = 6
x = 4
sum(x) = 10
x = 5
sum(x) = 15
In the above code snipped the x
variable is the counter and the sumx
variable is the accumulator. The accumulator sums up the iterator in each
round and adds it to the already accumulated sum of previous iterations.
It is bad programming style if you re-assign the iterator variable
x
within the code block that gets repeated and you should avoid it. Some
programming languages will not even allow you to assign a value to an iterator
within a loop statement.
4.2.3. Loop to Calculate the Product of Numbers¶
Here is another example. We write a loop that calculates the factorial of a
number: \(3!\). Remember that \(3! = 1 * 2 * 3\). In order to make
this happen we write a loop that sets \(i = 1, 2,\) and 3 and multiplies it
with the product of the previous round. The variable n_fac
stores the
product from each round.
import math as m
n = 6
n_fac = 1
for i in range(n):
print("i = ", i)
n_fac = n_fac * (i+1)
print("The factorial of {} is: {}".format(n, n_fac))
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
The factorial of 6 is: 720
Using a different method we can also calculate the factorial as:
Here the accumulator variable n_fac
is not accumulating a sum of numbers
but a product.
print("The factorial of 6 is {}".format(m.factorial(6)))
The factorial of 6 is 720
4.2.4. Loop to Print the Elements stored in a List¶
Finally, here is an example where we loop through the values of a list again. In each round we “grab” a number from the list and print it.
Let’s first define a list with some numbers in it.
xv = list(range(5))
print("xv= {}".format(xv))
xv= [0, 1, 2, 3, 4]
We now start the loop and pick each value of this list one-by-one. The
command length
tells us how many arguments are in the list xv
and then
lets the loop run from 1 to the total number of arguments in xv
.
Note also the difference in the two print commands, where the second one
results in formatted output.
xv = list(range(6))
for i in range(len(xv)):
print("i= {}".format(i))
print("xv[i]= {:4.2f}".format(xv[i]))
i= 0
xv[i]= 0.00
i= 1
xv[i]= 1.00
i= 2
xv[i]= 2.00
i= 3
xv[i]= 3.00
i= 4
xv[i]= 4.00
i= 5
xv[i]= 5.00
4.2.5. Loop with Iterator Values Not Starting at Zero¶
If you use the range(5)
command in the previous example, Python will
generate an internal list with the values [0,1,2,3,4] and then let the loop
run through the values of this list so that the iterator variable will start
with value 0
, then increment to value 1
in the second round, then increment to
3
in the third round and so on.
If you want the iterator variable of the loop to take on certain values and not
start from 0
you can specify the range command slightly differently and give it
a new starting value such as range(3, 6)
would generate an internal list of
[3,4,5]
and then let the iterator variable run through that list in each
round of the loop.
Note
Python uses half open intervals in its internal list generation processes.
This means that the interval you hand into the range
command in
mathematical notation is [3,6). This means it’s closed at the bottom and open
on top. Closed at the bottom means that the number 3
is included in the
interval and open on top means that the number 6
is excluded from the
interval.
Here is an example of a loop where the iterator variable does not start with value zero.
for i in range(3,6):
print('i = {}'.format(i))
i = 3
i = 4
i = 5
4.2.6. Nested Loops¶
In this section you will see an example of a loop inside a loop, or a nested loop.
for i in range(3,6):
print('Inside first loop but outside second loop i = {}'.format(i))
for j in range(100, 105):
print('Inside second loop: i = {} and j = {}'.format(i,j))
Inside first loop but outside second loop i = 3
Inside second loop: i = 3 and j = 100
Inside second loop: i = 3 and j = 101
Inside second loop: i = 3 and j = 102
Inside second loop: i = 3 and j = 103
Inside second loop: i = 3 and j = 104
Inside first loop but outside second loop i = 4
Inside second loop: i = 4 and j = 100
Inside second loop: i = 4 and j = 101
Inside second loop: i = 4 and j = 102
Inside second loop: i = 4 and j = 103
Inside second loop: i = 4 and j = 104
Inside first loop but outside second loop i = 5
Inside second loop: i = 5 and j = 100
Inside second loop: i = 5 and j = 101
Inside second loop: i = 5 and j = 102
Inside second loop: i = 5 and j = 103
Inside second loop: i = 5 and j = 104
As you can see the first loop gets executed and the iterator variable i
takes on value 3. Then the code jumps to the “inside” loop and executes the
repetitions for iterator variable j
.
4.2.7. Looping through the Content of a List¶
If you already have a list predefined and you want to loop through the content
of that list you can use a for
loop in a more direct way without explicitly
indexing the list elements inside of brackets []
.
# Define the list
myList = ['jim', 'james', 23, 12, 'car', 'bike']
for x in myList:
print('indexing variable x is: ', x)
indexing variable x is: jim
indexing variable x is: james
indexing variable x is: 23
indexing variable x is: 12
indexing variable x is: car
indexing variable x is: bike
If you need to keep track of the position of the various items in the list you
can use the enumerate
command which internally generates a “zipped list”
that pairs up each element in the list with its index inside of the list. Here
is an example using the previous list:
# Define the list
myList = ['jim', 'james', 23, 12, 'car', 'bike']
for i, x in enumerate(myList):
print('variable i is: {} and x is: {}'.format(i, x))
variable i is: 0 and x is: jim
variable i is: 1 and x is: james
variable i is: 2 and x is: 23
variable i is: 3 and x is: 12
variable i is: 4 and x is: car
variable i is: 5 and x is: bike
4.2.8. Combining Lists and Looping Through Them¶
If you have two or more lists that you want to loop through simultaneously
pulling the first elements from both lists (in tandem), followed by the second
elements from both lists, etc. you can use the zip
command. The zip
function “glues” or “zips” the lists together and then allows you to run (or
loop) through them in this pairwise fashion. The next example illustrates this.
# Define the list of spouses
myMaleList = ['jim', 'james', 'jack', 'john', 'jason']
myFemaleList = ['emma', 'clara', 'susan', 'jill', 'lisa']
for husband, wife in zip(myMaleList, myFemaleList):
print('The hubby is: {} and the wife is {}'.format(husband, wife))
The hubby is: jim and the wife is emma
The hubby is: james and the wife is clara
The hubby is: jack and the wife is susan
The hubby is: john and the wife is jill
The hubby is: jason and the wife is lisa
If you want to combine this with the index of the names inside the lists you
can use enumerate
again. Be careful in how you use the parenthesis around
the variables husband
and wife
in the for
loop construct.
# Define the list of spouses
myMaleList = ['jim', 'james', 'jack', 'john', 'jason']
myFemaleList = ['emma', 'clara', 'susan', 'jill', 'lisa']
for i, (husband, wife) in enumerate(zip(myMaleList, myFemaleList)):
print("""At index: {} the hubby is: {}
and the wife is {}""".format(i, husband, wife))
At index: 0 the hubby is: jim
and the wife is emma
At index: 1 the hubby is: james
and the wife is clara
At index: 2 the hubby is: jack
and the wife is susan
At index: 3 the hubby is: john
and the wife is jill
At index: 4 the hubby is: jason
and the wife is lisa
4.3. While Loop¶
The while loop runs and keeps repeating to do something until a certain stopping condition is met.
4.3.1. While Loop 1¶
In the first example we let the iterations run as long as the value of variable
x
is smaller than 10. In every iteration we increase x by one unit, so that in
effect the loop gets repeated 9 times.
In a while
loop the iterator variable is not automatically incremented as
in the for
loop, where we explicitly state the starting and stopping values
for the iterator variable. We therefore have to make sure that we increment the
iterator/counter variable x
within the repeatable codeblock using x = x
+1
or shorter and more efficiently x += 1
.
x = 0
y = 0
while (x < 10):
y = y + x
print("X= {} and Y= {}".format(x, y))
x += 1 # i.e., x = x + 1
X= 0 and Y= 0
X= 1 and Y= 1
X= 2 and Y= 3
X= 3 and Y= 6
X= 4 and Y= 10
X= 5 and Y= 15
X= 6 and Y= 21
X= 7 and Y= 28
X= 8 and Y= 36
X= 9 and Y= 45
The accumulator variable y
calculates the cumulative sum of all numbers
from 1 to 9, so that \(y = 0+1+2+...+9\). If you forget the statement that
increments the counter at the end of the repeatable code block within the loop,
then the loop will run infinitely long and you have to break the code with
pressing ctrl
+ c
which will stop the execution of the Python script.
4.3.2. While Loop 2¶
In this last example we calculate how long it takes to repay a loan. The longer you wait to repay the loan, the more interest is accumulated and added to the outstanding debt. The key formula in this example is:
r = 0.11 # Annual interest rate
# Time between repayments in years (i.e., monthly repayments)
period = 1.0/12.0
debt_initial = 1000.0 # Initial debt
payments = 12.0 # Amount repaid each period
mytime = 0
debt = debt_initial
while (debt > 0):
mytime = mytime + period
debt = debt*(1. + r*period) - payments
print("Loan will be repaid in: {} years.".format(mytime))
Loan will be repaid in: 13.250000000000025 years.
4.4. Combining Branching Statements and Loops¶
We can of course combine everything we have learned so far. Let’s assume you have the following programming task. You have to generate a list with numbers from 1 to 20. You then have to collect all numbers from 1 to 10 in a blue bin and add them up. All numbers from 11 to 20 are to be added up in the bin. How would you do that?
You use a loop that runs through all the numbers of a list and combine it with a branching statement that checks whether a number is smaller than 11. If YES (i.e., numbers are smaller 11) execute one block of code where the numbers are collected in a blue bin and if NO (i.e., numbers are greater 10) then put those numbers into the red bin.
Here is the example code that would accomplish this.
blueBin = 0
redBin = 0
for i in range(1,21):
if i <= 10:
print('Number i = {:2d} will be put in BLUE bin'.format(i))
blueBin = blueBin + i
else:
print('Number i = {:2d} will be put in RED bin'.format(i))
redBin = redBin + i
print(' ')
print('------------------------------------------- ')
print('The sum of numbers in BLUE bin is {}'.format(blueBin))
print('The sum of numbers in RED bin is {}'.format(redBin))
print('------------------------------------------- ')
Number i = 1 will be put in BLUE bin
Number i = 2 will be put in BLUE bin
Number i = 3 will be put in BLUE bin
Number i = 4 will be put in BLUE bin
Number i = 5 will be put in BLUE bin
Number i = 6 will be put in BLUE bin
Number i = 7 will be put in BLUE bin
Number i = 8 will be put in BLUE bin
Number i = 9 will be put in BLUE bin
Number i = 10 will be put in BLUE bin
Number i = 11 will be put in RED bin
Number i = 12 will be put in RED bin
Number i = 13 will be put in RED bin
Number i = 14 will be put in RED bin
Number i = 15 will be put in RED bin
Number i = 16 will be put in RED bin
Number i = 17 will be put in RED bin
Number i = 18 will be put in RED bin
Number i = 19 will be put in RED bin
Number i = 20 will be put in RED bin
-------------------------------------------
The sum of numbers in BLUE bin is 55
The sum of numbers in RED bin is 155
-------------------------------------------
4.5. Time Your Work¶
Sometimes it is useful to know how long it takes for a script to run through.
In order to accomplish this you can use the time()
function from the time
library. When you call it, it gives you the current time.
You would therefore
call the time function at the beginning of your script and store that value in
some variable, say tic
. This is followed by your “main code” that works
through a series of commands. At the end of the script you call for the current
time again and store it in a variable, say, toc
. Then you simply take the
difference between tic
and toc
variable and you’ll have your elapsed
time period. Here’s an example that times a “large” while loop.
import time # Imports system time module to time your script
tic = time.time()
x = 0
while (x < 1000000):
# add some stuff that needs to be calculated, e.g.
y = y + x
x += 1
toc = time.time()
print("Time elapsed = {} seconds".format(toc - tic))
Time elapsed = 0.14289498329162598 seconds
4.6. Key Concepts and Summary¶
Note
A branching statment allows you to split your code into alternative execution blocks.
A loop statement allows you to execute code blocks repeatedly.
You can nest loops inside of each other and you can nest branching statements as well.
4.7. Self-Check Questions¶
Todo
Generate a list with entries from 14 to 40 with stepsize 2.
Write a loop that divides the first 10 entries of your list above by 5
Write a loop that replaces all the elements of your list with elements that are half a big. If you list says
[1,2,3,4]
your new list should read[0.5,1,1.5,2]
.