Program Flow and Structure
Contents
%matplotlib inline
import matplotlib.pyplot as plt
from math import sin, cos, tan, pi, acos
from graphviz import Digraph
graph_attr = dict(
rankdir='LR',
# size='30',
splines='ortho'
)
start_node = dict(
shape='box',
style='rounded, filled',
fillcolor='#e5f5e0',
color="#a1d99b"
)
instr_node = dict(
shape='box',
style='filled',
fillcolor='#d9d9d9',
color="#bdbdbd"
)
branch_node = dict(
shape="diamond",
style="filled",
fillcolor="#cab2d6",
color="#6a3d9a"
)
dummy_attr = dict(
shape = "point",
width = "0",
)
Program Flow and Structure¶
A program consists of commands, which are executed in a certain order. This order is called the process flow. The following types of structures describe the process flow:
Sequence
Branching
Iteration
With those structures, the process flow can be described by flow charts.
To illustrate the various structures we will use a package called myturtle.
MyTurtle¶
MyTurtle is a simple package that is used for educational purposes. It allows to navigate a cursor across a screen, which then draws a line.
We need to import
the functionality from the package which we want to use. In this case, we need to run
from myturtle import Turtle
We now can create Turtle
objects.
t = Turtle()
First the cursor appears at position (0, 0) and points in positive x-direction.
Information about possible commands and their arguments can be accessed with via the documentation of the Turtle
class.
Turtle?
Init signature: Turtle(color='k')
Docstring:
Turtel cursor class
The turtle can turn left or right and move forward. It will draw a line
if drawing is switch on, which it is by default. This version of turtle is
using matplotlib for drawing and may be used in Jupyter notebooks.
Methods:
--------
left(turn=90): turn left by `turn` degrees
right(turn=90): turn right by `turn` degrees
forward(distance=1): move forward by `distance`
set_draw(draw=True): set draw state to either True or False
reset(): reset prosition and angle of the turtle to initial values
File: ~/anaconda3/envs/pherwiss_programming/lib/python3.8/site-packages/myturtle/turtle.py
Type: type
Subclasses:
To get help about a certain method, e.g. forward
, use again the ?
syntax.
Turtle.forward?
Signature: Turtle.forward(self, distance=1)
Docstring:
Move forward
Parameter:
---------
distance: numeric, default=1. Distance to move forward
File: ~/anaconda3/envs/pherwiss_programming/lib/python3.8/site-packages/myturtle/turtle.py
Type: function
Sequence¶
A Sequence is the simplest process flow. Every command is executed step by step. Every task follows exactly one new task.
Example:
t = Turtle()
t.forward(1)
t.left(120)
t.forward(1)
t.left(120)
t.forward(1)
t.left(120)
The corresponding flow chart looks like this:
Branching¶
In many cases, one would like the program to execute a task only if a certain condition is met.
This is called branching.
In Python, as in most other high-level languages, branching is done with an if
structure.
The syntax is as follows:
if <condition>:
<conditional code>
<unconditional code>
where <condition>
is a statement that can be interpreted as True
or False
.
The part which is only executed conditional must be indented.
It does not matter how it is indented, but it must be consistent within the block of conditional code.
The convention is to use 4 white spaces for indentation.
Here is an example:
t = Turtle()
t.forward(3.2)
if t.x > 3:
t.left(180)
t.forward(t.x - 3)
t.left(180)
t.left(180)
t.forward(1)
The corresponding flow chart is
fc = Digraph()
fc.attr(**graph_attr)
for i, (s, attr) in enumerate(zip(
(
'start', 'forward(3)', 'x > 3', 'left(180)', 'forward(x - 3)',
'left(180)', 'left(180)', 'forward(1)', 'end'
),
(start_node, instr_node, branch_node) + 5 * (instr_node,) + (start_node,)
)):
fc.node(str(i), s, **attr)
fc.edges(['01', '12', '34', '45', '56', '67', '78'])
fc.edge('2', '3', xlabel='yes')
fc.edge('2', '6', xlabel='no', constraint='false')
fc
The flow chart shows that the process is branched at the purple node. Depending on the result of the condition, only one branch of the program is executed. In this example, there are two possible branches in the process flow. Unlike for sequences, it is now possible that an instruction may follow two preceding ones or two instructions may follow on one preceding one.
The process can also be split into more than two branches using alternative conditions.
To do this you use the elif
statement together with an condition or the else
statement which contains the code if none of the conditions is met.
Here is one example and the corresponding flow chart.
t = Turtle()
t.forward(1)
if 1 <= t.x < 2:
t.left(45)
elif 2 <= t.x < 3:
t.left(90)
elif 3 <= t.x < 4:
t.left(135)
else:
t.left(180)
t.forward(1)
Iteration¶
In many cases a tasks shall be repeated as long as a specific condition holds or the task shall be executed for each element of a list.
For those cases structured programing languages offer loops.
In Python, two loop structures are available: the while
and the for
loop.
While Loop¶
The while
loop executes a code block as long as a specific condition is fulfilled.
This code block is called loop body and we say the program iterates the loop body.
The syntax is
while <condition>:
<loop body>
Note that the condition is always checked when entering the loop body. See the example below with the respective flow chart.
t = Turtle()
while t.x <= 5:
t.forward(1)
break
and continue
¶
In all types of loops the iteration can be aborted with a break
statement.
This terminates the loop and the program jumps to the first instruction after the loop body.
A break
can be used to define alternative conditions for a while
loop or the check the termination condition at a different location in the flow chart.
To only stop the current iteration, the continue
statement is used.
On encountering a continue
, the program jumps to the end of the loop body and starts the next iteration.
See the example below and the corresponding flow chart.
t = Turtle()
while t.x <= 5:
t.forward(0.1)
if t.y > 2:
break
if t.x > 3:
continue
t.left(1)
For Loop¶
The for
loop is a counting loop.
The loop body is executed for all elements of a sequence, e.g. a list of integers or any other object.
For every iteration the respective object from the sequence is assigned to a variable.
for i in [0, 1, 2, 3]:
print(i)
0
1
2
3
Of course, loops can also be nested. Here is an example to find all prime numbers between 2 and 99:
for n in range(2, 100):
for x in range(2, n):
if n % x == 0:
break
else:
print("{:d} is a prime number".format(n))
2 is a prime number
3 is a prime number
5 is a prime number
7 is a prime number
11 is a prime number
13 is a prime number
17 is a prime number
19 is a prime number
23 is a prime number
29 is a prime number
31 is a prime number
37 is a prime number
41 is a prime number
43 is a prime number
47 is a prime number
53 is a prime number
59 is a prime number
61 is a prime number
67 is a prime number
71 is a prime number
73 is a prime number
79 is a prime number
83 is a prime number
89 is a prime number
97 is a prime number
Useful functions for iterations¶
Besides range()
, python provides further useful functions to iterate over sequences.
In particular, the following should be mentioned:
enumerate(seq): Returns the elements of a sequence together with a counter.
for i, element in enumerate(['a', 'b', 'c', 'd']):
print(i, element)
0 a
1 b
2 c
3 d
zip(seq1, seq2, …): Takes multiple sequences and returns a tuple of the respective elements for each iteration.
for n, v, a in zip(('ham', 'spam', 'eggs'),
('is', 'was', 'has been'),
('good', 'mouldy', 'sticky')):
print(n, v, a)
ham is good
spam was mouldy
eggs has been sticky