52
6. Fruitful functions — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/fruitful_functions.html[1/4/2012 9:37:16 PM]
4. Write a function that helps answer questions like ‘“Today is Wednesday. I leave on holiday in 19
days time. What day will that be?”’ So the function must take a day name and a
delta argument
— the number of days to add — and should return the resulting day name:
Hint: use the first two functions written above to help you write this one.
5. Can your
day_add function already work with negative deltas? For example, -1 would be
yesterday, or -7 would be a week ago:
If your function already works, explain why. If it does not work, make it work.
Hint: Play with some cases of using the modulus function % (introduced at the beginning of the
previous chapter). Specifically, explore what happens to
x % 7 when x is negative.
6. Write a function
days_in_month which takes the name of a month, and returns the number of
days in the month. Ignore leap years:
If the function is given invalid arguments, it should return None.
7. Write a function
to_secs that converts hours, minutes and seconds to a total number of seconds.
Here are some tests that should pass:
8. Extend
to_secs so that it can cope with real values as inputs. It should always return an integer
number of seconds (truncated towards zero):
9. Write three functions that are the “inverses” of
to_secs:
1.
hours_in returns the whole integer number of hours represented by a total number of
seconds.
2.
minutes_in returns the whole integer number of left over minutes in a total number of
seconds, once the hours have been taken out.
3.
seconds_in returns the left over seconds represented by a total number of seconds.
You may assume that the total number of seconds passed to these functions is an integer. Here
test(day_num("Halloween"), None);
test(day_add("Monday", 4), "Friday")
test(day_add("Tuesday", 0), "Tuesday")
test(day_add("Tuesday", 14), "Tuesday")
test(day_add("Sunday", 100), "Tuesday")
test(day_add("Sunday", -1), "Saturday")
test(day_add("Sunday", -7), "Sunday")
test(day_add("Tuesday", -100), "Sunday")
test(days_in_month("February"), 28)
test(days_in_month("December"), 31)
test(to_secs(2, 30, 10), 9010)
test(to_secs(2, 0, 0), 7200)
test(to_secs(0, 2, 0), 120)
test(to_secs(0, 0, 42), 42)
test(to_secs(0, -10, 10), -590)
test(to_secs(2.5, 0, 10.71), 9010)
test(to_secs(2.433,0,0), 8758)
63
6. Fruitful functions — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/fruitful_functions.html[1/4/2012 9:37:16 PM]
are some test cases:
10. Which of these tests fail? Explain why.
11. Write a
compare function that returns
1 if
a > b,
0 if
a == b, and
-1 if
a < b
12. Write a function called
hypotenuse that returns the length of the hypotenuse of a right triangle
given the lengths of the two legs as parameters:
13. Write a function
slope(x1, y1, x2, y2) that returns the slope of the line through the points (x1,
y1) and (x2, y2). Be sure your implementation of
slope can pass the following tests:
Then use a call to
slope in a new function named
intercept(x1, y1, x2, y2) that returns the y-
intercept of the line through the points
(x1, y1) and
(x2, y2)
14. Write a function called
is_even(n) that takes an integer as an argument and returns True if the
argument is an even number and False if it is odd.
Add your own tests to the test suite.
15. Now write the function
is_odd(n) that returns True when
n is odd and False otherwise. Include
unit tests for this function too.
Finally, modify it so that it uses a call to
is_even to determine if its argument is an odd integer,
and ensure that its test still pass.
16. Write a function
is_factor(f, n) that passes these tests:
test(hours_in(9010), 2)
test(minutes_in(9010), 30)
test(seconds_in(9010), 10)
test(3 % 4, 0)
test(3 % 4, 3)
test(3 / 4, 0)
test(3 // 4, 0)
test(3+4 * 2, 14)
test(4-2+2, 0)
test(len("hello, world!"), 13)
test(compare(5, 4), 1)
test(compare(7, 7), 0)
test(compare(2, 3), -1)
test(compare(42, 1), 1)
test(hypotenuse(3, 4), 5.0)
test(hypotenuse(12, 5), 13.0)
test(hypotenuse(24, 7), 25.0)
test(hypotenuse(9, 12), 15.0)
test(slope(5, 3, 4, 2), 1.0)
test(slope(1, 2, 3, 2), 0.0)
test(slope(1, 2, 3, 3), 0.5)
test(slope(2, 4, 1, 2), 2.0)
test(intercept(1, 6, 3, 12), 3.0)
test(intercept(6, 1, 1, 6), 7.0)
test(intercept(4, 6, 12, 8), 5.0)
53
6. Fruitful functions — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/fruitful_functions.html[1/4/2012 9:37:16 PM]
index
next |
previous |
How to Think Like a Computer Scientist: Learning with Python 3 »
An important role of unit tests is that they can also act as unambiguous “specifications” of what
is expected. These test cases answer the question
Do we treat 1 and 15 as factors of 15?
17. Write
is_multiple to satisfy these unit tests:
Can you find a way to use
is_factor in your definition of
is_multiple?
18. Write the function
f2c(t) designed to return the integer value of the nearest degree Celsius for
given tempurature in Fahrenheit. (
hint:
you may want to make use of the built-in function,
round. Try printing
round.__doc__ in a Python shell or looking up help for the
round function, and
experimenting with it until you are comfortable with how it works.)
19. Now do the opposite: write the function
c2f which converts Celcius to Fahrenheit:
©
Copyright 2011, Peter Wentworth, Jeffrey Elkner, Allen B. Downey and Chris Meyers. Created using
Sphinx 1.0.7.
test(is_factor(3, 12), True)
test(is_factor(5, 12), False)
test(is_factor(7, 14), True)
test(is_factor(7, 15), False)
test(is_factor(1, 15), True)
test(is_factor(15, 15), True)
test(is_factor(25, 15), False)
test(is_multiple(12, 3), True)
test(is_multiple(12, 4), True)
test(is_multiple(12, 5), False)
test(is_multiple(12, 6), True)
test(is_multiple(12, 7), False)
test(f2c(212), 100) # boiling point of water
test(f2c(32), 0) # freezing point of water
test(f2c(-40), -40) # Wow, what an interesting case!
test(f2c(36), 2)
test(f2c(37), 3)
test(f2c(38), 3)
test(f2c(39), 4)
test(c2f(0), 32)
test(c2f(100), 212)
test(c2f(-40), -40)
test(c2f(12), 54)
test(c2f(18), 64)
test(c2f(-48), -54)
69
7. Iteration — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/iteration.html[1/4/2012 9:37:23 PM]
index
next |
previous |
How to Think Like a Computer Scientist: Learning with Python 3 »
7. Iteration
Computers are often used to automate repetitive tasks. Repeating identical or similar tasks without making errors
is something that computers do well and people do poorly.
Repeated execution of a set of statements is called iteration. Because iteration is so common, Python provides
several language features to make it easier. We’ve already seen the
for statement in chapter 3. This the the form of
iteration you’ll likely be using most often. But in this chapter we’ve going to look at the
while statement — another
way to have your program do iteration, useful in slightly different circumstances.
Before we do that, let’s just review a few ideas...
7.1. Reassignment
As we have mentioned previously, it is legal to make more than one assignment to the same variable. A new
assignment makes an existing variable refer to a new value (and stop referring to the old value).
The output of this program is:
because the first time
bruce is printed, its value is 5, and the second time, its value is 7.
Here is what reassignment looks like in a state snapshot:
With reassignment it is especially important to distinguish between an assignment statement and a boolean
expression that tests for equality. Because Python uses the equal token (
=) for assignment, it is tempting to
interpret a statement like
a = b as a boolean test. Unlike mathematics, it is not! Remember that the Python token
for the equality operator is
==.
Note too that an equality test is symmetric, but assignment is not. For example, if
a == 7 then
7 == a. But in
Python, the statement
a = 7 is legal and
7 = a is not.
Furthermore, in mathematics, a statement of equality is always true. If
a == b now, then
a will always equal
b. In
Python, an assignment statement can make two variables equal, but because of the possibility of reassignment,
they don’t have to stay that way:
The third line changes the value of
a but does not change the value of
b, so they are no longer equal. (In some
programming languages, a different symbol is used for assignment, such as
<- or
:=, to avoid confusion. Python
chose to use the tokens
= for assignment, and
== for equality. This is a popular choice also found in languages like
C, C++, Java, and C#.)
7.2. Updating variables
1
2
3
4
bruce = 5
print(bruce)
bruce = 7
print(bruce)
5
7
1
2
3
a = 5
b = a # after executing this line, a and b are now equal
a = 3 # after executing this line, a and b are no longer equal
68
7. Iteration — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/iteration.html[1/4/2012 9:37:23 PM]
When an assignment statement is executed, the right-hand-side expression (i.e. the expression that comes after
the assignment token) is evaluated first. Then the result of that evaluation is written into the variable on the left
hand side, thereby changing it.
One of the most common forms of reassignment is an update, where the new value of the variable depends on its
old value.
Line 2 means get the current value of n, multiply it by three and add one, and put the answer back into n as
its new value. So after executing the two lines above,
n will have the value 16.
If you try to get the value of a variable that doesn’t exist yet, you’ll get an error:
Before you can update a variable, you have to initialize it, usually with a simple assignment:
This second statement — updating a variable by adding 1 to it — is very common. It is called an increment of the
variable; subtracting 1 is called a decrement. Sometimes programmers also talk about bumping a variable, which
means the same as incrementing it by 1.
7.3. The
for loop revisited
Recall that the
for loop processes each item in a list. Each item in turn is (re-)assigned to the loop variable, and the
body of the loop is executed. We saw this example in an earlier chapter:
Running through all the items in a list is called traversing the list, or traversal.
Let us write a function now to sum up all the elements in a list of numbers. Do this by hand first, and try to isolate
exactly what steps you take. You’ll find you need to keep some “running total” of the sum so far, either on a piece
of paper, or in your head. Remembering things from one step to the next is precisely why we have variables in a
program: so we’ll need some variable to remember the “running total”. It should be initialized with a value of zero,
and then we need to traverse the items in the list. For each item, we’ll want to update the running total by adding
the next number to it.
1
2
n = 5
n = 3*n + 1
>>> w = x + 1
Traceback (most recent call last):
File "<interactive input>", line 1, in
NameError: name 'x' is not defined
>>> x = 0
>>> x = x + 1
1
2
3
for f in ["Joe", "Amy", "Brad", "Angelina", "Zuki", "Thandi", "Paris"]:
invitation = "Hi " + f + ". Please come to my party on Saturday!"
print(invitation)
1
2
3
4
5
6
7
8
9
10
11
12
13
def mysum(xs):
""" Sum all the numbers in the list xs, and return the total. """
running_total = 0
for x in xs:
running_total = running_total + x
return running_total
#add tests like these to your test suite ...
test(mysum([1, 2, 3, 4]), 10)
test(mysum([1.25, 2.5, 1.75]), 5.5)
test(mysum([1, -2, 3]), 2)
test(mysum([ ]), 0)
test(mysum(range(11)), 55) # 11 is not in the list.
90
7. Iteration — How to Think Like a Computer Scientist: Learning with Python 3
http://openbookproject.net/thinkcs/python/english3e/iteration.html[1/4/2012 9:37:23 PM]
7.4. The
while statement
Here is a fragment of code that demonstrates the use of the
while statement:
You can almost read the
while statement as if it were English. It means, While
v is less than or equal to
n, continue
executing the body of the loop. Within the body, each time, increment
v. When
v passes
n, return your accumulated
sum.
More formally, here is precise flow of execution for a
while statement:
1. Evaluate the condition, yielding False or True.
2. If the condition is false, exit the
while statement and continue execution at the next statement.
3. If the condition is true, execute each of the statements in the body and then go back to step 1.
The body consists of all of the statements below the header with the same indentation.
This type of flow is called a loop because the third step loops back around to the top. Notice that if the condition is
false the first time through the loop, the statements inside the loop are never executed.
The body of the loop should change the value of one or more variables so that eventually the condition becomes
false and the loop terminates. Otherwise the loop will repeat forever, which is called an infinite loop. An endless
source of amusement for computer scientists is the observation that the directions on shampoo, lather, rinse,
repeat, are an infinite loop.
In the case here, we can prove that the loop terminates because we know that the value of
n is finite, and we can
see that the value of
v increments each time through the loop, so eventually it will have to exceed
n. In other cases,
it is not so easy to tell.
What you will notice here is that the
while loop is more work for you — the programmer — than the equivalent
for
loop. When using a
while loop one has to control the loop variable yourself: give it an initial value, test for
completion, and then make sure you change something in the body so that the loop terminates. By comparison,
here is an alternative function that uses
for instead:
Notice the slightly tricky call to the
range function — we had to add one onto
n, because
range generates its list up
to but not including the value you give it. It would be easy to make a programming mistake and overlook this, but
because we’ve made the investment of writing some unit tests, our test suite would have caught our error.
So why have two kinds of loop if
for looks easier? This next example shows a case where we need the extra power
that we get from the
while loop.
7.5. The 3n + 1 sequence
Let’s look at a simple sequence that has fascinated and foxed mathematicians for many years. They still cannot
answer even quite simple questions about this.
1
2
3
4
5
6
7
8
9
10
11
12
def sum_to(n):
""" Return the sum of 1+2+3 ... n """
ss = 0
v = 1
while v <= n:
ss = ss + v
v = v + 1
return ss
# for your test suite
test(sum_to(4), 10)
test(sum_to(1000), 500500)
1
2
3
4
5
6
def sum_to(n):
""" Return the sum of 1+2+3 ... n """
ss = 0
for v in range(n+1):
ss = ss + v
return ss
Documents you may be interested
Documents you may be interested