Tải bản đầy đủ (.pdf) (510 trang)

Ebook The practice of computing using python (2nd edition) Part 2

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (9.54 MB, 510 trang )

P A R T


3

Functions and Data
Structures

Chapter 6 Functions—QuickStart
Chapter 7 Lists and Tuples
Chapter 8 More on Functions
Chapter 9 Dictionaries and Sets
Chapter 10 More Program Development


This page intentionally left blank




C H A P T E R

6

Functions---QuickStart

Function, the exercise, or executing of some office or charge.
T. Blount, Glossographia, 1656, earliest definition of function
in the Oxford English Dictionary
YOU HAVE SEEN MANY EXAMPLES OF USING PYTHON BUILT-IN FUNCTIONS AND


methods. In Section 4.3.1, we took at look at how functions work and how we could use them
to manipulate string objects. In this chapter, you’ll learn how to create your own functions.
The concept of a function should be familiar from its use in mathematics. Functions
in programming languages share many of the characteristics of mathematical functions but
add some unique features as well that make them more useful for programming.
One of the main advantages for using functions is that they support divide-and-conquer
problem solving. Remember divide-and-conquer from Section 3.4.5? This technique encourages you to break a problem down into simpler subproblems, solve those subproblems,
and then assemble the smaller solutions into the overall solutions. Functions are a way to
directly encode the “smaller subproblem” solution. You’ll see more about this as we work
through this chapter.

6.1 W H A T I S A F U N C T I O N ?
In mathematics,
a function defines the relationship between values. Consider the function

f (x ) ⇒ x . If you provide a particular value of x , e.g., x = 4, the function will perform
a calculation (here the square root operation) and return the associated value, e.g., 2.
Mathematicians term the variable x the argument to the function and say that the function
returns the value 2.
It is possible for a function to have multiple arguments—for example, a function that calculates multiplication requires two arguments: f (x , y ) ⇒ x ∗ y . However, a mathematical

257


258

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T


function returns only one object. Note that the returned object can be a compound object—
an object with multiple elements. For example, when working with graph paper, each point
is represented by by its x and y coordinates, an ordered pair (x , y ). A function that returns an
ordered-pair object does indeed return a single value, but it is a value with multiple elements,
the x and y values. An example of such a function would be the mirror function. The mirror
function swaps the x and y values of the ordered pair: f (x , y ) ⇒ (y , x ). The notion that
the object a function returns can be a compound object is very useful, including in Python.
Python functions share many of the characteristics of mathematical functions. In particular, a Python function:
r Represents a single operation to be performed
r Takes zero or more arguments as input
r Returns one value (potentially a compound object) as output

A function is also important because it represents an encapsulation. By encapsulation,
we mean that the details of an operation can be hidden, providing coarser operations that
we as programmers can use without having to understand the function’s internal details. A
function can represent the performance of an operation without making the reader plow
through the details of how the operation is actually performed.
Consider the sqrt function with respect to encapsulation. There are many ways to
calculate a square root that vary in accuracy and speed. Remember, we saw a particular
approach that we called the Babylonian square root approach in Section 3.5. Other implementations exist. However, each implementation, each method, represents the “square root”
operation. Each method takes in an argument and returns that object’s square root. As long
as the result is correct, we need not be concerned with the details of how the operation is
performed. That is encapsulation.

6.1.1 Why Have Functions?
As you progress in learning to program, you’ll move from essential programming elements
to important programming elements. Selection (if) and repetition (while) are essential
programming constructs. It is difficult to write any program without using these two essential
features. Functions, on the other hand, allow us to write better code in the sense that it is
more readable. Also, because functions allow us to divide programs into smaller pieces, they

assist in divide-and-conquer problem solving. In that way, functions make programs easier
to write. Finally, once a function is written, it can be shared and used by other programmers
(including ourselves). Thus, functions provide a powerful construct that we can use to make
our programs easier to read, write, and maintain.
From this point on, many of the programming elements we introduce will make
some tasks easier and will subsequently make writing and understanding (that is, reading)
the program easier. You could write programs without them, but those programs would be
more difficult to read, write, and maintain.


6.2 •

PYTHON

FUNCTIONS

259

In more detail, functions provide the following features, which help in programming:
r Divide-and-conquer problem solving: As we have already mentioned, functions
r

r
r

r

r

divide programs into smaller pieces, an approach that corresponds nicely to a divideand-conquer approach to problem solving (introduced in Section 3.4.5).

Abstraction: Functions provide a higher-level interface to operation that the function
implements. By encapsulating details, functions provide a programmer with a high-level
view of the function’s operation that could be implemented in multiple ways—possibly
by someone else. By analogy, consider how you drive a car. It has a simple interface that
hides considerable complexity. Your car has many options—for example, fuel-injection,
turbo, or many others. Does the existence of these options change that basic interface
you have to the car—i.e., turn the wheel, hit the gas, press the brake? Do you understand
how fuel injection provides better performance for your car than a carburetor does? Do
you care? You don’t have to know the difference: you simply drive the car. Abstraction
means that the operation the function represents (drive the car) can be implemented
in many ways that do not affect the basic car interface. The underlying operations can
also be changed (upgrade the engine) without changing the interface.
Reuse: Once a function has been created, it can be reused. If you write a function that
locates strings in a database, then anywhere that functionality is needed can use that
function. The more such a function is needed, the “simpler” the code that uses it.
Sharing: Once your function is well tested, you can distribute it for use by other people.
Those people can further test the function, refine its capabilities, and through improvement provide a service to everyone in the field. Useful functions can be collected into
modules for sharing. Sharing of modules is one of Python’s strengths, as programmers
generously share modules in many diverse areas.
Security: You hear again and again of security breaches in code: phone companies,
computer distributors, software companies, etc. One way to battle security issues is
the use of functions. Small pieces of code can be more easily vetted and security (and
other issues) more easily addressed. Once they have been approved, they can be used
to construct other secure components, which can also be reused, and so on. Building
securely from the bottom up is one approach to writing secure code.
Simplification and readability (duplication removal): Because a function provides an
encapsulation, it can be used to simplify a program and make it more readable. Anywhere
that multiple lines of code might be needed to address a problem, a function can replace
those lines. If the replacement can be done in multiple places, the result is simpler code.


6.2 P Y T H O N F U N C T I O N S
There are two parts to a Python function, and they correspond to the two parts found in
mathematical functions:1 the definition and the invocation. The definition defines (creates)
the function; the invocation is the application of the function in a program. A function
1

Some languages, such as those derived from C (C++, Java, C#), have a third part—the declaration.


260

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

definition is the second way we have seen to create a name associated with an object in
Python, the first being an assignment statement.
Consider an example function that converts Celsius temperatures to Fahrenheit.
r First we need a conversion formula: C ∗ 1.8 + 32
r Mathematics has a function invocation:

f a hr e nhe it = f (C )
where the definition of the function is:
f (C ) = C ∗ 1.8 + 32
r Python has a function invocation that looks very much like the mathematical one:
fahrenheit = f(C)

but the Python definition looks quite different:
def f(celsius float):
return celsius float* 1.8 + 32


As in mathematics, C is called an argument of the function. The celsius float
variable is termed a parameter of the function. Upon invoking the function, the argument
C’s value is passed to the parameter value celsius float for use in the calculation.2
More detail on the passing of values between arguments and parameters can be found in
Section 8.1.1.
A function definition begins with the keyword def. The Python definition works
similarly to an assignment statement. By executing a def statement, a new name is created
in the namespace and a new object, a function object, is associated with that name. As we
have observed elsewhere in Python, everything is an object, and functions are no different.
The def is a compound statement, meaning that it provides a suite of other Python
statements and expressions that are part of the function. The suite of statements are what
will constitute the calculation done by the function object. One of the special keywords
that can be used in functions is the return statement. The return indicates a value
that is returned as output from the function invocation. A function’s operation ends after a
return statement is executed. A function may have more than one return statement, but
the first one that is executed will end the function’s operation. (We have used the phrase “to
invoke a function,” but an equivalent and frequently used phrase is “to call a function.”)
The general form of a function is shown in Figure 6.1.
Let’s create a function to do our temperature conversion and use it in a session.
Note the parts of the function: the def and return keywords as well as the parameter
(celsius float). Finally, notice the indentation for the suite of statements, part of the
2

Note that to adhere to our naming convention, the argument C should have been named better, such as celsius float, but we
left it as plain C so that it looked more like the mathematical function.


6.2 •


Function name.
Must follow variable
naming rules.
def
Keyword
indicating
function is
being defined.

function_name

PYTHON

FUNCTIONS

List of parameters being
passed: in parenthesis,
comma separated.

(parameter1, parameter2)

statement1
statement2
return value_to_return
Return statement
indicates the
value returned
when the function finishes.

261


:
Suite of the
function
follows the
colon.

Function suite:
contains code to
perform some action.
Indented.

FIGURE 6.1 Function parts.

function definition. We will discuss the special comment with triple quotes (""") later. In
essence, it is a brief description of the function and is called a docstring.

Code Listing 6.1
1

# Temperature conversion

2
3

def celsius to fahrenheit(celsius float):

4

""" Convert C e l s i u s to Fahrenheit . """


5

return celsius float * 1.8 + 32

>>> ================================ RESTART ================================
>>>
>>> celsius to fahrenheit
<function celsius to fahrenheit at 0xcc22f0>
>>> celsius to fahrenheit(100)
212.0
>>> celsius to fahrenheit(0)
32.0
>>> new fn()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>


262

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

NameError: name 'new fn' is not defined
>>> new fn = "a string object"
>>> new fn
'a string object'
>>> new fn()
Traceback (most recent call last):

File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>>

Notice that Code Listing 6.1 contains only the function definition—no invocation.
When the file is run (we press the F5 key in IDLE), the def statement is executed, the name
of the function is added to the namespace, and a function object is created. That function
object is associated with the function’s name in the namespace. We can type the name of
the function and see that it is associated with a function object. We can then invoke (call)
the function and see what results are returned. Python recognizes to call/invoke a function
when a name is followed by parentheses, which may or may not contain a list of arguments.
It is the parentheses that mark the invocation, and the name adjacent to the parentheses
is the function invoked. In the session, we converted 100◦ C to 212◦ F and 0◦ C to 32◦ F. If
the function is not defined, or if the object associated with a name is not a function object,
then an error occurs, as is shown in the session.

6.3 F L O W O F C O N T R O L W I T H F U N C T I O N S
Functions introduce a new flow of control model. Up to this point, a program has essentially
been a series of statements and expressions that are executed in the order in which they appear
in the file. Some of the statements introduce local control paths within those statements,
such as with selection or repetition, but the flow remains sequential in the file. With
functions, we create a set of small, independent subprograms that can be used to construct
a larger program.
In short, the flow of control with functions is to flow from the invocation (call) in
the calling program, to the function itself, and then back to the calling program with
the function’s return value being made available to the calling program. Control within a
function remains sequential: one statement after another along with local control statements
such as if and while.
For every program, there is usually one “main” part where execution begins. After that,
the flow of control is based on the order of both statements and functions. In particular

for functions, operation of a function is determined by when it is invoked, not when it is
defined. Functions can be defined anywhere in the program file, as long as they are defined
before they are invoked. Functions must be defined before use because the function name
must be placed in the namespace before it can be called.
Figure 6.2 shows an example of function control flow.


6.3 • FLOW

OF

CONTROL

WITH

FUNCTIONS

263

Main program
statement
Call

fahrenheit = celsius_to_fahrenheit(25)

Function
def celsius_to_fahrenheit(celsius):

statement
Retu


statement

rn

val = celsius * 1.8 + 32
return val

FIGURE 6.2 Function flow of control.

6.3.1 Function Flow in Detail
Consider two programs: the caller, the program presently executing, and the function. In this
example, the caller is the main program, the program where execution begins. A caller executes its statements until it encounters a function invocation, celsius to fahrenheit
(25) in Figure 6.2. At that point, the caller temporarily suspends, and the function
begins. Thus, one program is suspended (the caller) waiting for a result from the now
executing function. When the function finishes execution, the suspended caller receives
the return value from the function and the main program (caller) resumes execution from
that point.
Because the function is essentially a new program, the function gets its own namespace
when it begins execution. Any object that gets created and given a name (by assignment,
by a def, etc.) within the function is placed in the function’s separate namespace, not the
main program’s (caller’s) namespace. If a new name is created in the function that is the
same as a name that existed in the caller’s namespace, the newly created association is used
in the function. This protocol has some interesting consequences, which we will explore in
Section 8.1.1.

6.3.2 Parameter Passing
VideoNote 6.1
Simple Functions


Parameter passing is the passing of values from a calling program to a function, so
that the function can perform its operation. You will remember that the function
celsius to fahrenheit had a single argument, called C. The function had a single parameter called celsius float. Parameter passing is the passing of values from
argument to parameter.
Parameter passing is done just before the calling program suspends. The caller associates
its argument values to the corresponding function parameter in the function object. In
Figure 6.2, the argument value 25 is associated with the parameter celsius. The parameter
is then defined in the function’s namespace and associated with the value of its corresponding
argument. After that, function operation begins.


264

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

Argument values are typically passed to parameter names in the order they are listed.3
The names of the corresponding argument and parameter need not match. Only the order
matters: the first argument value is passed to the first parameter, the second argument value
to the second parameter, and so on. The number of arguments and parameters must match.4
Again, after values are passed, the function then begins execution.
During function execution, if a return statement is executed, the function ends
and the return value is provided to the caller (“return” arrow in Figure 6.2). For example,
fahrenheit = celsius to fahrenheit(25) assigns the returned value to the main
program variable fahrenheit as shown in Figure 6.2. After the function ends, the caller
continues.
Code Listing 6.2 is a sample program with a function that takes in a Celsius temperature
to convert to Fahrenheit.


Code Listing 6.2
1

# Conversion program

2
3

def celsius to fahrenheit(celsius float):

4

""" Convert C e l s i u s to Fahrenheit . """

5

return celsius float * 1.8 + 32

6
7
8
9

# main part o f the program
print("Convert Celsius to Fahrenheit.")
celsius float = float(input("Enter a Celsius temp: "))

10

# c a l l the conversion function


11

fahrenheit float = celsius to fahrenheit(celsius float)

12

# print the returned value

13

print(celsius float," converts to ",fahrenheit float," Fahrenheit")

>>> ================================ RESTART ================================
>>>
Convert Celsius to Fahrenheit.
Enter a Celsius temp: 100
100.0 converts to 212.0 Fahrenheit
>>> ================================ RESTART ================================
>>>
Convert Celsius to Fahrenheit.
Enter a Celsius temp: 0
0.0 converts to 32.0 Fahrenheit
3
4

Python also has other ways to pass argument values to parameters. See Chapter 8.
In Chapter 8 you will learn about default values, which allow fewer arguments than parameters.



6.3 • FLOW

OF

CONTROL

WITH

FUNCTIONS

265

Lines 3–5 define the function. Notice def beginning the compound statement, the
parameter (celsius float), and the return with its associated expression within
the function suite. To repeat, the def statement is executed by Python and creates the
function. Once created, it can be called (invoked) by another program. Remember, a
function must be defined (the def statement must be executed) before a program can
call the function.
Lines 7–13 are the “main” program.
Line 9 prompts the user for input.
Line 11 invokes (calls) the function. The value in the argument celsius float
is passed to the parameter celsius float. Then control passes to the function. When the function ends, it returns a value that the main program assigns to
fahrenheit float.
Line 13. The main program continues with Line 13 and prints the results.

Check Yourself: Simple Functions Check
1. Given the function make odd, what are the results of the four function invocations
(print statements)?
def make_odd(n):
return 2*n + 1

print(make_odd(2))
print(make_odd('2'))
n = 3
print(make_odd(n))
print(1 + make_odd(3))

2. Write a function make even(n).
What happens if you use a string as an argument?
Why is the behavior different then with make odd(n)?

6.3.3 Another Function Example
You have used the len function to find the length of a string. Let’s write our own version
of that function that performs the same operation. We will name our function length to
avoid confusion with the Python built-in len.
Here is an algorithm to find the length of a string, S.
r Initialize a counter: count = 0
r Iterate through each character of the string using a for loop: for char in a str:
r When each character is encountered in the for loop, add 1 to the counter:
count += 1


266

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

Let’s put the algorithm in a function by adding the word def and a return statement.
Then we can “run” the function (F5 in IDLE) so it is loaded into the Python shell, where
we can invoke it. We deviate from our naming convention, assuming that count is an int

and that char is a string.

Code Listing 6.3
1

def length(a str):

2
3
4
5
6

>>>
>>>
>>>
>>>
19
>>>
19

""" Return the length o f a str """
count = 0
for char in a str:
count += 1
return count

================================ RESTART ================================
question = "What is your quest?"
length(question) # our function

len(question)

# the Python built−in function

With a length function in hand, let’s modify it. Suppose that instead of a count of
the number of characters in the string, we wanted a count of only the letters in the string.
That is, we will ignore characters other than lowercase alphabetic letters (such as numbers,
spaces, punctuation, etc.) Our algorithm is similar:
r Initialize a counter.
r Iterate through each character of the string using a for loop.
r For each character in the string, if the character is a letter, add 1 to the counter.

The change in the algorithm is small, but the implementation takes a little more
thought. How do we check “if the character is a letter”? One way to do that is to create
a variable associated with a string of all the lowercase letters. We can then check if each
character we encounter in the parameter a str is in (remember in tests for membership)
the lowercase letters. However, Python has created for us a number of these strings that
we can test against. As discussed in Section 4.6.2, we could use a variable from the string
module, the string string.ascii lowercase. Finally, we must consider what to do
with uppercase letters. We have a choice: we could ignore them (not include them in the
count), or we could include them by converting every a str character to lowercase before


6.3 • FLOW

OF

CONTROL

WITH


FUNCTIONS

267

we test for membership. We can handle that by making the character lowercase before
checking to see whether it is in the string of letters. We will call our modified function
letter count.

Code Listing 6.4
1

import string

2
3

def letter count(a str):

4
5
6
7
8
9

>>>
>>>
>>>
>>>

19
>>>
15

""" Return the count o f l e t t e r s in a str . """
count = 0
for char in a str:
if char.lower() in string.ascii lowercase:
count += 1
return count

================================ RESTART ================================
question = "What is your quest?"
len(question)
letter count(question)

Of course, there are many different algorithms to solve our letter-counting problem.
For example, we could have made a new string object resulting from the concatenation of
string.ascii lowercase and string.ascii uppercase and check for membership in that string.

6.3.4 Function Example: Word Puzzle
Let’s use strings and functions to solve a word puzzle.
Find a word that contains the vowels a, e, i, o, and u in that order in a string.

To solve a word puzzle, we need a list of words.

Reading a File of Words
Many word lists can be found on the Internet by searching for either “word lists” or
“dictionary,” usually with one word per line. We can download a dictionary and save it in a



268

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

file; let’s name the file dictionary.txt. We have worked with files in Section 5.7.1 and will do
so in more detail in Chapter 14, but let’s review how to read the contents of a file.
To read through the file, one line at a time, we do the following:
r Open the file for reading.
r Read through the file one line at a time.

A Python program that reads through the whole file dictionary.txt, and simply prints
each line of the file is Code Listing 6.5:

Code Listing 6.5
# Print a l l words in a d i c t i o n a r y f i l e that has one word per l i n e
# open f i l e named " d i c t i o n a r y . t x t " f o r reading ( ' r ' )
data file = open("dictionary.txt", 'r')

# i t e r a t e through the f i l e one l i n e at a time
for line str in data file:
print(line str)

Interestingly, this program prints the lines of the file in double-space format. Why is
that?5

Searching a File of Words
Now that you remember how to read through a file of words, let’s try to solve our puzzle.

First, we need to handle a common feature of a file’s strings: there are often some
characters that we don’t want to deal with. In this case, the dictionary file contains a carriagereturn character at the end of each line, and it may contain stray characters such as spaces or
tabs. We can eliminate such characters using the strip string method, one of the methods
listed in Section 4.3.4. If no arguments are provided to strip, then a new string is returned
with whitespace removed from either end of the calling string. The calling string is not
modified. If a string argument is provided to strip, only those characters in the argument
string are removed. An example of its use is a str.strip('., '), which returns a new
string that strips commas, periods, and the space character from the beginning and end of
a str. In particular, ", this.".strip('., ') and " this,,.".strip('., ')
both return the new string object 'this'. The blank character in the argument string is
hard to see (after all, it is a blank), but it is there!
5

Each line already has a carriage return in the line. The print function adds another, hence double-spaced.


6.3 • FLOW

OF

CONTROL

WITH

FUNCTIONS

269

PROGRAMMING TIP
The strip method works only on the beginning and end of a string. For example,

'this string'.strip() returns the string 'this string'. Because no arguments
are provided, the default behavior is to return a new string where whitespace (tabs, carriage
returns, space characters, etc.) are removed from the ends, but the space in the middle of the
string is unaffected. Note that all the whitespace characters are removed from the beginning
and the end.
For every line we fetch from the file, we strip that line to remove whitespace at the
beginning and end of the line. In addition, word puzzles are often easier if all characters
are known to be only lowercase (or only uppercase). The string method lower is useful
for that. Let’s create a function that strips out whitespace characters and makes all of the
remaining characters lowercase.

Code Listing 6.6
def clean word(word):

""" Return word in l o w e r c a s e s t r i p p e d o f whitespace . """
return word.strip().lower()

Notice the use of chained method invocation in the function as described in
Section 4.3.2.
As our word puzzle requires a word with all five vowels in order, the word must be at
least six characters long, so there is no reason to consider shorter words. We can add that
check and the clean word function to our file-reading program.

Code Listing 6.7
# Find a word with a s i n g l e example o f the vowels a , e , i , o , u in that order
data file = open("dictionary.txt", "r")
def clean word(word):

""" Return word in l o w e r c a s e s t r i p p e d o f whitespace . """
return word.strip().lower()


# main program
for word in data file:
# f o r each word in the f i l e
word = clean word(word) # clean the word


270

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

if len(word) <= 6:
continue
print(word)

# s k i p word i f too small to have a l l vowels

Our program still does nothing to solve our puzzle, but we now have a framework to
work in: a program that reads a file of words and returns each word stripped of extraneous
characters.

Solving the Puzzle
To solve this puzzle, we want to determine the vowels and their order in a word. Let’s write
a function that returns the vowels found in a word in the order in which they were found. A
function lets us consider each word in isolation. For any word, we can check each character
to see whether it is a vowel and collect the vowels into a string in the order in which they
were found. To begin, we create a variable that is associated with the empty string, with the
intent that we will add discovered vowels to that string. Our algorithm is:

r Create an empty string; let’s call it vowels in word.
r For each character char in the word
- if char is a vowel, add it to the string vowels in word.
How do we check whether a character is a vowel? We can create a string of vowels
vowels str and associate it with 'aeiou' and check to see whether each character in
the dictionary entry word is in (is a member of ) vowels str.

Here is our algorithm implemented as a function.

Code Listing 6.8
def get vowels in word(word):

""" Return vowels in s t r i n g word−−include r e p e a t s . """

vowel str = "aeiou"
vowels in word = ""
for char in word:
if char in vowel str:
vowels in word += char
return vowels in word

Let’s try the function out in a session to find the vowels in the word 'create'. The
vowels in 'create' in order are 'eae'.
>>> word = "create"
>>> get vowels in word(word)
'eae'


6.3 • FLOW


OF

CONTROL

WITH

FUNCTIONS

271

Our function appears to be working. Of course, we need to check it more thoroughly,
but as always we will leave that as an exercise for you to try on your own.
Now that we have a function that extracts the vowels in a word, we can consider our
puzzle again. The puzzle requires a word with exactly the five vowels in order. That is, if
our get vowels in word function returns exactly 'aeiou', we have found our puzzle
answer. Our refined algorithm to solve the puzzle is:
r Open the file.
r For each word in the file
- strip the word.
- if the word is too small, skip it.
- get the vowels in the word.
- if the vowels returned is exactly 'aeiou', print the original word.
Using that algorithm as the main part of our program, let’s put it all together.

Code Listing 6.9
1

# Find a word with a s i n g l e example o f the vowels a , e , i , o , u in that order

2

3

data file = open("dictionary.txt", "r")

4
5

def clean word(word):

6

""" Return word in l o w e r c a s e s t r i p p e d o f whitespace . """

7

return word.strip().lower()

8
9
10
11
12
13
14
15
16

def get vowels in word(word):

""" Return vowels in s t r i n g word−−include r e p e a t s . """


vowel str = "aeiou"
vowels in word = ""
for char in word:
if char in vowel str:
vowels in word += char
return vowels in word

17
18
19
20
21
22
23
24
25

# main program
print("Find words containing vowels 'aeiou' in that order:")
for word in data file:
# f o r each word in the f i l e
word = clean word(word) # clean the word
if len(word) <= 6:
# i f word i s too small , s k i p i t
continue
vowel str = get vowels in word(word) # g e t vowels in word
if vowel str == 'aeiou':
# check i f you have e x a c t l y a l l


vowels in order
26

print(word)


272

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

>>>
Find words containing vowels 'aeiou' in that order:
facetious
>>>

Check Yourself: Function Practice with Strings
1. Give the output provided by the following program on the indicated input values.
def func1 (str1, str2):
if str1 > str2:
result_str = str1[1:]
else:
result_str = str2[:-1]
return result_str
# main program}
response1_str = input("Enter a string:")
response2_str = input("Enter a second string:")
print(func1(response1_str, response2_str))
print(func1(response2_str, response1_str))


# Line 1
# Line 2

(a) Given the two input values (in order), abc123 and then bcd456, what output
is produced by Line 1?
(b) Given the two input values (in order), abc123 and then bcd456, what output
is produced by Line 2?
(c) Given the two input values (in order), aaabbc and then aaabbcd, what
output is produced by Line 1?
(d) Given the two input values (in order), aaabbc and then aaabbcd, what
output is produced by Line 2?

The dictionary.txt file we used for the example contained almost 40,000 words,
and our puzzle-solving program found only one that satisfied the criterion of having the
vowels 'aeiou' in that order: facetious. A larger dictionary (we found one with over
234,000 words) returned a longer list, as shown in the following session.
>>>
Find words containing vowels 'aeiou' in that order:
abstemious
abstemiously
abstentious
acheilous
acheirous


6.3 • FLOW

OF


CONTROL

WITH

FUNCTIONS

273

acleistous
affectious
annelidous
arsenious
arterious
bacterious
caesious
facetious
facetiously
fracedinous
majestious
>>>

There are a couple of points that are worth noting about the example.
r The use of functions made our problem-solving task easier. The functions allowed us to

consider the problem in smaller pieces—the divide-and-conquer technique introduced
in Chapter 3
r The main program is very readable. Even if we did not know the implementation of
the functions clean word and get vowels in word we could guess what they
(likely) did and understand what the program was trying to do.
r Note the reuse of the identifier vowel str in both the main program and in the

function get vowels in word. Because the function gets its own namespace, these
identifiers are associated with different objects. More on this in Section 8.1.

6.3.5 Functions Calling Functions
There is no limitation to when a function can be called (except that it must be after its
def). It is often the case that a function will call another function. This extension does not
change the process described previously, though it does make the flow of control slightly
more complicated for us to follow. More on this in Chapter 8. In fact, a function can call
itself—a complicated control flow to which we devote Chapter 16.

6.3.6 When to Use a Function
There are no hard or fast rules about when to write something as a function or when to leave
code as part of a larger program. However, here are some guidelines that may prove helpful.
Only one purpose: A function should be the encapsulation of a single, identifiable operation. A function should do one thing, and of course, do it well. Functions that try to do
too many things are candidates to be broken into multiple functions (i.e., refactored).
Readable: A function should be readable. This is a reiteration of our venerable RULE 2 .
Not too long: A function shouldn’t be too long. What is “too long” depends on many
things, but the idea is that if a function does one thing, a person should be able to


274

CHAPTER

6 • F U N C T I O N S --- Q U I C K S T A R T

read it easily and understand its purpose. If the function is too long, difficult to follow
somehow, it might need to be broken into multiple functions.
Reusable: A function should be reusable in contexts other than the program it was written
for originally. If possible, the function should be self-contained and not dependent on

some nuance of the calling program. If it has dependencies then those dependencies
should be made clear so that others can use it more easily.
Complete: A function should be complete, in that it works in all potential situations. If you
write a function to perform one thing, you should make sure that all the cases where it
might be used are taken into account. It is often the case that the core of the function is
very straightforward, but handling all the cases it might encounter requires supporting
code.
Able to be refactored: We first mentioned the term refactoring in Section 2.2.9. Again,
refactoring is the process of taking existing code and modifying it such that its structure
is somehow improved but the functionality of the code remains the same. Functions can
play a prominent role in this process, as they allow you to take long, difficult-to-follow
code and break it into smaller, more manageable pieces. If you need to “fix” some code,
consider refactoring it into functions.
The idea that a function should “do one thing” is important enough that we will make it
a rule.
Rule 8: A function should do one thing.

PROGRAMMING TIP
A useful rule of thumb for novices is to keep each function small enough to fit on the screen.
Like all rules of thumb, there are many reasons to break the rule, but you should ask yourself
if there is a good reason to make a function longer than that.

6.3.7 What If There Is No Return Statement?
Sometimes we write functions without a return statement. Functions that do not return a
value are often called procedures.
In that case, what, if anything, is returned? The answer is that a special Python value
None is returned by default if the programmer does not provide a return statement.
None is a kind of odd Python value—a value to represent nothing. Kind of cosmic!
There are some good reasons to use a procedure. One that often comes up is specially
formatted output. Formatting output to look “pretty” can be laborious and potentially

complicated. A print procedure is therefore a good place to do such output. The procedure
isolates all the printing format but does not return a value. Other instances might require a
change of state to the program, something like turning a graphics mode on or off or changing


6.3 • FLOW

OF

CONTROL

WITH

FUNCTIONS

275

the network connection to a different mode. Each of these elements is best isolated as a
process, but as a function they do not need to return a value.
To see this process in action, let’s write a trivial function that simply prints its parameter.
We will then assign the result of the function to a variable. When we print the value of the
variable, we see that None was printed.
>>> def formatted output(my str, my int):
print('The result of the processing for',my str, 'was', my int)

# no return statement
...
>>> formatted output('Bill',100)
The result of the processing for Bill was
>>> result = formatted output('Fred',75)

The result of the processing for Fred was
>>> print(result)
None
>>>

100

# capture the i m p l i c i t return
75

# return value was None

6.3.8 What if There Are Multiple Return Statements?
If there are multiple return statements, the first return encountered during the operation of
the function stops the function at that point and returns that value. Consider the following
example function, which returns “positive,” “negative,” or “zero,” depending on the value
of the argument.
>>> def positive negative zero(number):
if number > 0:
return "positive"
if number < 0:
return "negative"
else: # number == 0
return "zero"
>>> positive negative zero(5) # t e s t a l l t h r e e p o s s i b l e c a s e s
'positive'
>>> positive negative zero(-2.5)
'negative'
>>> positive negative zero(0)
'zero'


Note that the function works correctly whether the argument passed in is an int or
a float. For that reason neither suffix is used in the name. Multiple return values can
make following the flow of control in the function more difficult for the reader to follow.
If possible, it is best to have as few returns as possible so the reader can more clearly follow
the function.


276

CHAPTER

6



F U N C T I O N S --- Q U I C K S T A R T

VISUAL VIGNETTE

6.4 TURTLE FLAG

VideoNote 6.2
Problem design
using functions

The first official United States flag was established by the Continental Congress on
June 14, 1777, with first Flag Act: “Resolved, That the flag of the United States be made
of thirteen stripes, alternate red and white; that the union be thirteen stars, white in a blue
field, representing a new Constellation.” The arrangement of the stars was not specified:

Betsy Ross used a circle, others used rows.
Drawing a flag is an excellent illustration of the practicality of functions. In abstraction,
the United States flag is a composition of two shapes: stars and stripes (rectangles). It is
impractical to draw the 13 (or 50!) stars individually when a function can encapsulate the
multiple steps required for each star. The same can be said for drawing the 13 stripes—they
are simply rectangles. Even the blue field behind the stars is a rectangle, as is the overall
shape. Therefore, to draw the flag using Python’s Turtle graphics, one will want at least two
functions: draw star and draw rectangle. The program is left as an exercise.

Summary
In this chapter, we introduced the concept of functions in a programming language and
showed how functions work in Python. Of particular importance is that functions aid us in
the divide-and-conquer approach to problem solving. After covering the list data structure
in the next chapter, we revisit functions to examine the complexities of passing mutable
objects to functions.

Functions

r Working with functions requires two elements: a function definition and a function

invocation (call).
r Control transfers from the calling point to the function.


EXERCISES

277

r Caller’s arguments map to the function’s parameters in order left to right.
r A function has its own namespace.

r Parameters are in the function’s namespace.
r A function must be defined before it is called.
r Defining a function puts its name in the caller’s namespace.
r Syntax, function definition:
def function name(parameter list):

# statement suite
return # something

Rules

r RULE 1: Think before you program!
r RULE 2: A program is a human-readable essay on problem solving that also happens

to execute on a computer.
r RULE 3: The best way to improve your programming and problem skills is to practice!
r RULE 4: A foolish consistency is the hobgoblin of little minds.
r RULE 5: Test your code, often and thoroughly!
r RULE 6: If it was hard to write, it is probably hard to read. Add a comment.
r RULE 7: All input is evil, until proven otherwise.
r RULE 8: A function should do one thing.

Exercises
1. Draw the parts of a function and label the parts. Write a brief definition for each part.
2. What are three guidelines used to determine whether creating a separate function is the
sensible thing to do?
3. What does this function do? What does it return for num = 5?
def Func(number):
total = 0
while number > 0:

total = total + number*(number-1)
number = number - 1
return total


278

CHAPTER

6



F U N C T I O N S --- Q U I C K S T A R T

4. What does this function do? What does it return if x = 5?
def Func(x):
total = 0
for i in range(x):
total += i * (i-1)
return total

5. What does this function do? What number is returned by this function?
def Func():
number = 1.0
total = 0
while number < 100:
total = 1//number

number+=1

return total

6. Write a function that takes mass as input and returns its energy equivalent (E = mc 2 ).
The units should be in the meter-kilogram-second system.
7. Menu writing:
(a) A common task while writing any software is to display a menu and ask the user
for a choice. One such example is the menu on your cellphone. It has messaging,
contacts, games, settings, media, and web (and possibly others) as options. Write a
function called display menu that displays the menu to the user and allows the
user to make a choice (using input).
(b) Write a function that takes the choice of the user and makes calls to the other
functions that correspond to the operation to be performed. (Give meaningful
names to the functions. You don’t have to write the other function definitions.)
8. Write a function that takes in the final scores of two soccer teams as arguments and
prints either who won the game or whether the game was tied. Refer to the teams as
“Team1” and “Team2.” The function returns nothing.
9. Write a function that takes as input an English sentence (a string) and prints the total
number of vowels and the total number of consonants in the sentence. The function
returns nothing. Note that the sentence could have special characters like dots, dashes,
and so on.


EXERCISES

279

10. The Fibonacci sequence is: 1, 1, 2, 3, 5, 8, 13 . . . You can see that the first and second
numbers are both 1. Thereafter, each number is the sum of the previous two numbers.
(a) Write a function to print the first N numbers of the Fibonacci sequence.
(b) Write a function to print the Nth number of the sequence.

11. Suppose you are purchasing something online on the Internet. At the website, you get
a 10% discount if you are a member. Additionally, you are also getting a discount of
5% on the item because its Father’s Day.
Write a function that takes as input the cost of the item that you are purchasing and
a Boolean variable indicating whether you are a member (or not), applies the discounts
appropriately, and returns the final discounted value of the item.
Note: The cost of the item need not be an integer.
12. A leap year in the Gregorian calendar system is a year that’s divisible by 4 but not by
100, unless it is also divisible by 400. For example, 1896, 1904, and 2000 were leap
years but 1900 was not. Write a function that takes in a year as input and prints whether
it’s a leap year (or not).
13. Error checking with meaningful error messages is an important part of programming.
Consider the following scenario: A customer has to pay his monthly credit card bill.
The credit limit on the card is $1000. The minimum payment due is always $20.
Let the payment on the credit card be $P. Write a function called make payment(P)
that takes as an argument the total payment on the credit card ($P) and prints “Success”
or “Retry.” Try to think of all the errors that should be taken care of and implement
those in the function. One example would be that if the payment is less than $20, the
program should remind the user that it’s less than the minimum payment due.
14. You buy an international calling card to India. The calling card company has some
special offers.
(a)
(b)
(c)
(d)

If you charge your card with $5 or $10, you don’t get anything extra.
For a $25 charge, you get $3 of extra phone time.
For a $50 charge, you get $8 of extra phone time.
For a $100 charge, you get $20 of extra phone time.


Write a function that asks the user for the amount he/she wants on the card and returns
the total charge that the user gets. Note: Values other than those mentioned above are
not allowed.
15. Chat:
(a) In certain chat programs or messaging applications, there is a limit on the number
of characters that you can send in a message. Write a function that takes as input
the message (a string) and checks whether the number of characters is less than
160 (or not). If the length of the message is less than 160, the message should be
returned. If the length of the message is greater than 160, a string consisting of only
the first 160 characters should be returned.


×