© Paul Gerrard 2016
Paul GerrardLean Python10.1007/978-1-4842-2385-7_3

3. Program Structure

Paul Gerrard
(1)
Maidenhead, Berkshire, UK
 

Decision Making

Some simple utilities might be a short list of statements run in order, but a useful program usually needs to make decisions and choices. The decision making in a program determines the path that the program takes. Decisions are made by if statements.

The if Statement

if statements depend on some form of test or condition. The normal format of an if statement is shown here:
if test:               # note the colon ':'.
   statement1          # The statements following the
   statement2          # if are indented and executed
   statement3          # if the test is True.
In this case, the three statements are executed if test is True. Otherwise these statements are skipped and the interpreter skips to the statement following the code block.
Often, the False outcome of the test has its own code block, as follows:
if test:               # note the colon ':'.
   DoThis()            # DoThis() ... if test=True
else:                  # note the colon after 'else'
   DoThat()            # DoThat() ... if test=False
The else: keyword separates the True outcome of the test from the False outcome of the test and directs the compiler to take the alternate code block: DoThat().
So far, we’ve seen a binary decision with only a True and a False outcome. Some if statements make a choice from more than two alternatives. In this case, the elif: keyword separates the different choices and the else: keyword is the final choice if no other test is met. For example:
1   If code=='RED':
2       SoundRedAlert()
3   elif code=='AMBER':
4       GiveWarning()
5   else:
6       pass
Note
that the indentation of the if and its corresponding elif and else keywords must all be the same.

The pass Statement

In the preceding example, depending on the value of code, the program makes a choice to do something, but the third choice was pass. The pass statement is a “do nothing” statement. The third clause (else) is not strictly necessary, but pass is often useful to show explicitly what the program is doing (or not doing).

Types of Test

The tests that are applied in an if statement can take many forms, but the main patterns are summarized here.
  • Comparisons
    var1 > var2       # greater than
    var1 == var2      # equal to
    var1 != var2      # not equal to
  • Sequence (list, tuple, or dictionary) membership
    var in seq
    var not in seq
  • Sequence length
    len(x)>0       # sequence has entries?
  • Boolean value
    fileopen       # fileopen==True?
    not fileopen   # fileopen==False?
  • Has a value?
    var            # not None (or zero or '')
  • Validation
    var.isalpha()    # alphanumeric?
    var.isdigit()    # is all digits?
  • Calculations
    (price*quantity) > 100.0 # cost>100?
    (cost-budget) > 0.0      # overbudget?
In the case of calculations it is often better to use braces to force the calculations than to rely on the default operator precedence.
Some decisions are more complex and require multiple tests to implement. For example:
if hungry and foodInFridge and notTooTired:
    cookAMeal()
else:
    getTakeAway()
In this case, the and operator joins the three conditions and all must be True for cookAMeal() to be executed.
There are three logical operators—and, or, and not—that can be used to link decisions.
Decisions can be nested; that is, they can appear inside the indented code blocks of other decisions. For example:
if age>19:
    if carValue>10000:
        if gotConvictions:
           rejectInsuranceApplication()

Loops and Iteration

Some features need to perform activities repetitively to process a number of items, including the following:
  • Lists of values.
  • Entries in a dictionary.
  • Rows of data in a database.
  • Lines of text in a disk file.
These constructs, usually called loops, perform a defined code block repeatedly on some item of data until some condition or test is met (or not met). These loops are implemented using for and while statements.

For Statement

The for statement acts as a header statement for a code block that is to be executed until some condition is met. The for statement operates on an iterable set of elements, often a sequence.
>>> theTeam=['Julia','Jane','Tom','Dick','Harry']
>>> for person in theTeam:
...    print('%s is in the team' % person)
Julia is in the team
Jane is in the team
Tom is in the team
Dick is in the team
Harry is in the team
The general format is 'for var in seq:'.
For each iteration through the members of the sequence, the variable var takes the value of the entry in the list or tuple, or it takes the value of the key in a dictionary.
Sometimes we don’t want to iterate through a list or dictionary, but we want to execute a loop a specific number of times. Python provides a useful range() function that generates an iterable list of specific size for us. It can take three arguments—start, end, and step—that specify the first number, the maximum number, and the increment between elements in the generated range, respectively. If you provide just one number argument, it creates a list with that number of integer elements starting with zero.
>>> range(10)
range(0,10)         # a list of ten elements 0-9
>>> range(1,10)     # default step=1
range(1,10)         # list: [1,2,3,4,5,6,7,8,9]
>>> range(1,20,3)   # steps of 3
range(1,20,3)       # list: [1,4,7,10,13,16,19]
>>> for i in range(3):
...    print(i)
0
1
2

While Statement

The while statement is similar to the for statement in that it provides a header statement for a code block to be repeated a number of times. Instead of an iterable set of elements, the while statement repeats the loop until a test is not met.
>>> n=4
>>> while n>0:
...    print(n)
...    n-=1
4
3
2
1
Often, the condition to be met is a counter that is decremented in the loop or a Boolean value the value of which is changed inside the loop, and then the loop is terminated.
>>> foundSmith=False
>>> while not foundSmith:
...   name=getNextName()   # get next person record
...   if name=='smith':    # name is 'smith'?
              foundSmith=True

Break Statement

A break statement is used to terminate the current loop and continue to the next statement after the for or while code block.
1   while True:     # this is an infinite loop
2      command=input('Enter command:')
3      if command=='exit': # infinite till user exits
4           break              # skips to line 7
5       else:
6           doCommand(command) # execute command
7   print('bye')

Continue Statement1

A continue statement is used in the code block of a loop to exit from the current code block and skip to the next iteration of the loop. The while or for loop test is checked as normal.
1   while True:     # this is an infinite loop
2       command=input('Enter command:')
3       if len(command)==0:  # no command - try again
4           continue     # goes to next loop (line 1)
5       elif command=='exit': # user exit
6           print('Goodbye')
7           break        # skips to line 10
8       else:
9           doCommand(command)
10   print('bye')

List Comprehensions

A list comprehension (also known as a listcomp) is a way of dynamically creating a list of elements in an elegant shorthand. Suppose you wanted to create a list of the squares of the first ten integers. You could use this code:
squares=[]
for i in range(1,11):
   squares.append(i*i)
Or you could use this:
squares=[i*i for i in range(1,11)]
The syntax for listcomps is:
[expr for element in iterable if condition]
The if condition can be used to select elements from the iterable. Here are some examples of this syntax in use:
# a list of even numbers between 1 and 100
evens = [i for i in range(1,100) if not i % 2]
# a list of strings in lines containing 'True'
trulines = [l for l in lines if l.find('True')>-1]

Using Functions

Why Write Functions?

When you write more complicated programs, you can choose to write them in long, complicated modules, but complicated modules are harder to write and difficult to understand. A better approach is to modularize a complicated program into smaller, simpler, more focused modules and functions .
The main motivation for splitting large programs into modules and functions is to better manage the complexity of the process.
  • Modularization “divides and conquers” the complexity into smaller chunks of less complex code, so design is easier.
  • Functions that do one thing well are easier to understand and can be very useful to you and other programmers.
  • Functions can often be reused in different parts of a system to avoid duplicating code.
  • If you want to change some behavior, if it’s in a function, you only need to change code in one place.
  • Smaller functions are easier to test, debug, and get working.
Importantly, if you choose to use a function written by someone else, you shouldn’t need to worry too much how it works, but you need to trust it.2

What Is a Function?

A function is a piece of program code that is:
  • A self-contained coherent piece of functionality.
  • Callable by other programs and modules.
  • Passed data using arguments (if required) by the calling module.
  • Capable of returning results to its caller (if required).
You already know about quite a few built-in Python functions. One of these is the len() function. We just call len() and pass a sequence as a parameter. We don’t need to write our own len() function, but suppose we did write one of our own (for lists and dictionaries only). It might look something like this:
>>> def lenDictList(seq):
...    if type(seq) not in [list,dict]: # a seq?
...         return -1                   # no - fail!
...    nelems=0                         # length zero
...    for elem in seq:                 # for elem
...       nelems+=1                     # add one
...
... return nelems                       # length
...
The header line has a distinct format:
  • The keyword def to signify it is a new function.
  • A function name lenDictList (that meets the variable naming rules).
  • Braces to enclose the arguments (none, 1 or more).
  • A colon to denote the end of the header line.
The code inside the function is indented. The code uses the arguments in the function definitions and does not need to define them (they will be passed by the calling module). Here are some examples:
>>> l = [1,2,3,4,5]
>>> d = {1:'one',2:'two',3:'three'}
>>> lenDictList(l)
5
>>> lenDictList(d)
3
>>> lenDictList(34)
-1
Note that the real len() handles any sequence including tuples and strings and does better error-handling. This is a much oversimplified version.

Return Values

The results of the function are returned to the caller using the return statement. In the preceding example, there is one return value: the length of the list or dictionary provided or it is –1 if the argument is neither.
Some functions do not return a result; they simply exit.
It is for the programmer to choose how to design his or her functions. Here are some example return statements.
return
return True
return False
return r1, r2, r3
return dict(a=v1,b=v2)
# does not return a value
# True – perhaps success?
# False – perhaps a failure?
# returns three results
# returns a dictionary

Calling a Function

Functions are called by using their name and adding parentheses enclosing the variables or values to be passed as arguments. You know len() already. The other functions are invented to illustrate how functions are used.
>>> count = len(seq)      # length of a sequence
>>>
>>> # the call below returns three results, the
>>> # maximum, the minimum, and the average of
>>> # the numbers in a list
>>> max, min, average = analyse(numlist)
>>>
>>> # the next call provides three parameters
>>> # and the function calculates a fee
>>> fee = calculateFee(hours, rate, taxfactor)
Note
The number of variables on the left of the assignment must match the number of return values provided by the function.

Named Arguments

If a function just has a single argument, then you might not worry what its name is in a function call. Sometimes, though, not all arguments are required to be provided and they can take a default value. In this case you don’t have to provide a value for the argument. If you do name some arguments in the function call, then you must provide the named arguments after the unnamed arguments. Here is an example:
def fn(a, b, c=1.0):
return a*b*c
fn(1,2,3)
fn(1,2)
fn(1,b=2)
fn(a=1,b=2,c=3)
fn(1,b=2,3)
# 1*2*3 = 6
# 1*2*1 = 2 – c=default 1.0
# 1*2*1 = 2 – same result
# 1*2*3 = 6 - as before
# error! You must provide
# named args *after* unnamed
# args
Note
In your code, you must define a function before you can call it. A function call must not appear earlier in the code than the definition of that function or you will get an “undefined” error.

Variable Scope

The variables that are defined and used inside a function are not visible or usable to other functions or code outside the function. However, if you define a variable in a module and call a function inside that module, then that variable is available in the called function. If a variable is defined outside all the functions in a module, the variable is available to all of the functions in the module.3 For example:
sharedvar="I'm sharable"   # a var shared by both
                           # functions
def first():
   print(sharedvar)        # this is OK
   firstvar='Not shared'   # this is unique to first
   return
def second():
   print(sharedvar)        # this is OK
   print(firstvar)         # this would fail!
   return
Footnotes
1
In the examples that follow, the doCommand() function needs to be defined, of course.
 
2
All open source or free-to-use libraries come with a health warning, but if you see many references to a library on programmer web sites and in books, you can be reasonably confident that it works.
 
3
Sometimes it is convenient to create shared variables that save you time and the hassle of adding them as arguments to the functions in a module. If you use these variables as places to pass data between functions, though, you might find problems that are hard to diagnose. Treating them as readonly variables will reduce the chance of problems that are hard to debug.
 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.55.198