~mccane/practical-programming/trunk

59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
1
\chapter{Modules and TDD}
1 by Brendan McCane
Initial import into bzr for version 2009
2
\label{lec-tdd}
3
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
4
This chapter primarily deals with a development methodology called Test Driven Development (TDD). Before we get to TDD though, we need a couple of extra parts of python: modules and triple quoted strings.
57 by Brendan McCane
Reorganising for 2014 to take into account the two halves: basic stuff + advanced stuff.
5
1 by Brendan McCane
Initial import into bzr for version 2009
6
\section{Modules, files and the \pythoninline{import} statement}
7
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
8
A \myidx{module} is simply a Python file that contains
1 by Brendan McCane
Initial import into bzr for version 2009
9
definitions (usually function definitions). As programs get large, it
10
makes sense to separate the program into different modules. This
11
allows the programmer to minimize the complexity of the programming
12
task. Typically, similar functionality or related functions are
13
grouped into a single module and separate modules are as independent
14
of each other as possible. Creating your own modules is as easy as
57.1.29 by Nick Meek
--
15
creating a Python script with definitions in it; in fact you have already 
16
written lots of Python modules.
1 by Brendan McCane
Initial import into bzr for version 2009
17
18
The Python standard library contains a very large number of modules
19
for many different tasks. It is worthwhile browsing the library just
20
to get a feel for all the useful things it can do. The current
21
documentation can be accessed at:
22
\myurl{http://www.python.org/doc/current/library/index.html}, or by
23
choosing \menu{Help \rarr Python Docs ...} in IDLE. We will
24
look at the \pythoninline{doctest} module later in this lecture, and
30 by mccane at ac
Done corrections3 from Matthew.
25
throughout the course several other modules will be introduced.
1 by Brendan McCane
Initial import into bzr for version 2009
26
30 by mccane at ac
Done corrections3 from Matthew.
27
There are three ways of using \pythoninline{import} to import a module
57.1.29 by Nick Meek
--
28
and subsequently use what was imported. The \pythoninline{math} module contains many 
29
useful math functions, we will use it to illustrate:
1 by Brendan McCane
Initial import into bzr for version 2009
30
31
\begin{enumerate}
32
33
\item
34
35
\begin{python}
36
import math
37
print math.cos(math.pi/2.0)
38
\end{python}
57.1.28 by Nick Meek
Fixed Bug #1257101
39
This statement imports every function from the \pythoninline{math} module which
40
 are then accessed using dot notation.
1 by Brendan McCane
Initial import into bzr for version 2009
41
42
\item
43
44
\begin{python}
45
from math import cos, pi
46
print cos(pi/2.0)
47
\end{python}
39 by Brendan McCane
Still working through all these updates.
48
This statement imports only the definitions of \pythoninline{cos} and
1 by Brendan McCane
Initial import into bzr for version 2009
49
\pythoninline{pi} from the math library. Nothing else is imported.
50
\item
51
52
\begin{python}
53
from math import *
54
print cos(pi/2.0)
55
\end{python}
39 by Brendan McCane
Still working through all these updates.
56
This statement also imports everything from the \pythoninline{math}
1 by Brendan McCane
Initial import into bzr for version 2009
57
module, the difference being that dot notation is not needed to access
58
module members.
59
60
\end{enumerate}
61
%Also, do you need/want to include the Restart between each example, otherwise the previous import is still imported.
39 by Brendan McCane
Still working through all these updates.
62
It is more common to use the first or second alternative than the last.
63
The first has the advantage of avoiding naming conflicts (two
1 by Brendan McCane
Initial import into bzr for version 2009
64
different modules defining \pythoninline{cos} for example), at the
71 by Brendan McCane
The final version for 2014.
65
cost of lengthier function calls. The second has the
1 by Brendan McCane
Initial import into bzr for version 2009
66
opposite advantages and disadvantages.
67
4 by Brendan McCane
Have modified the order of the book a bit and changed a couple of sections around. In particular, moved strings part 1 to before files, which makes the files lecture more interesting.
68
We can use the \pythoninline{help} function to see the functions and
69
data contained within modules. The keyword module
70
contains a single function, \pythoninline{iskeyword}, which as its
71
name suggests is a boolean function that returns \pythoninline{True}
72
if a string passed to it is a keyword:
57.1.28 by Nick Meek
Fixed Bug #1257101
73
4 by Brendan McCane
Have modified the order of the book a bit and changed a couple of sections around. In particular, moved strings part 1 to before files, which makes the files lecture more interesting.
74
\begin{pythonInteractive}
75
>>> from keyword import *
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
76
>>> iskeyword("for")
4 by Brendan McCane
Have modified the order of the book a bit and changed a couple of sections around. In particular, moved strings part 1 to before files, which makes the files lecture more interesting.
77
True
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
78
>>> iskeyword("all")
4 by Brendan McCane
Have modified the order of the book a bit and changed a couple of sections around. In particular, moved strings part 1 to before files, which makes the files lecture more interesting.
79
False
80
>>>
81
\end{pythonInteractive}
82
The data item, \pythoninline{kwlist} contains a list of all the
83
current keywords in Python:
84
\begin{pythonInteractive}
85
>>> from keyword import *
86
>>> print kwlist
87
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif',
88
'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import',
89
'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try',
90
'while', 'with', 'yield']
91
>>>
92
\end{pythonInteractive}
93
We encourage you to check out \url{http://docs.python.org/library/}
94
to explore the extensive libraries that 
95
come with Python. There are so many treasures to discover!
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
96
1 by Brendan McCane
Initial import into bzr for version 2009
97
98
\section{Triple quoted strings}
99
In addition to the single and double quoted strings we first saw in
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
100
Lecture \ref{lec-variables}, Python also has \emph{triple quoted strings}. We will need triple quoted strings for Unit Testing (next section). Here are some examples:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
101
102
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
103
\begin{pythonInteractive}
104
>>> type("""This is a triple quoted string using 3 double quotes.""")
105
<type 'str'>
106
>>> type('''This triple quoted strings uses 3 single quotes.''')
107
<type 'str'>
108
>>>
109
\end{pythonInteractive}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
110
\end{minipage}
111
1 by Brendan McCane
Initial import into bzr for version 2009
112
Triple quoted strings can contain both single and double quotes inside
113
them:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
114
115
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
116
\begin{pythonInteractive}
117
>>> print '''"Oh no", she exclaimed, "Ben's bike is broken!"'''
118
"Oh no", she exclaimed, "Ben's bike is broken!"
119
>>>
120
\end{pythonInteractive}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
121
\end{minipage}
122
1 by Brendan McCane
Initial import into bzr for version 2009
123
Finally, triple quoted strings can span multiple lines:
124
125
\noindent
126
\begin{minipage}{\textwidth}
127
\begin{pythonInteractive}
128
>>> message = """This message will
129
... span several
130
... lines."""
131
>>> print message
132
This message will
133
span several
134
lines.
135
>>>
136
\end{pythonInteractive}
137
\end{minipage}
138
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
139
1 by Brendan McCane
Initial import into bzr for version 2009
140
\section{Unit testing with \pythoninline{doctest}}
141
\label{sec-doctest}
142
It is a common best practice in software development these days to
143
include automatic \myidx{unit testing} of source code. Unit testing
144
provides a way to automatically verify that individual pieces of code,
57.1.28 by Nick Meek
Fixed Bug #1257101
145
such as functions, are working correctly. This makes it possible to
1 by Brendan McCane
Initial import into bzr for version 2009
146
change the implementation of a function at a later time and quickly
147
test that it still does what it was intended to do.
148
Python has a built-in doctest module for easy unit testing. Doctests
149
can be written within a triple quoted string on the \emph{first line}
150
of the body of a function or script. They consist of sample
151
interpreter sessions with a series of inputs to a Python prompt
152
followed by the expected output from the Python interpreter.
153
The doctest module automatically runs any statement beginning with
154
$>$$>$$>$ (followed by a space) and compares the following line with the output from the
155
interpreter.
156
To see how this works, put the following in a script named
39 by Brendan McCane
Still working through all these updates.
157
\myurl{first\_doctest.py}\footnote{There are four underscores in
158
  \pythoninline{\_\_name\_\_}, two at the start and two at the end.}:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
159
160
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
161
\begin{python}
162
def is_divisible_by_2_or_5(n):
163
    """
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
164
    >>> is_divisible_by_2_or_5(8)
165
    True
1 by Brendan McCane
Initial import into bzr for version 2009
166
    """
167
168
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
169
if __name__ == "__main__":
1 by Brendan McCane
Initial import into bzr for version 2009
170
    import doctest
171
    doctest.testmod()
172
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
173
\end{minipage}
1 by Brendan McCane
Initial import into bzr for version 2009
174
57.1.28 by Nick Meek
Fixed Bug #1257101
175
The last three lines are what make doctest run. Put them in the main routine
1 by Brendan McCane
Initial import into bzr for version 2009
176
of any file that includes doctests. 
177
Running the script will produce the following output:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
178
179
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
180
\begin{pythonOutput}
181
**********************************************************************
182
File "myfunctions.py", line 3, in __main__.is_divisible_by_2_or_5
183
Failed example:
184
    is_divisible_by_2_or_5(8)
185
Expected:
186
    True
187
Got nothing
188
**********************************************************************
189
1 items had failures:
190
   1 of   1 in __main__.is_divisible_by_2_or_5
191
***Test Failed*** 1 failures.
192
\end{pythonOutput}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
193
\end{minipage}
1 by Brendan McCane
Initial import into bzr for version 2009
194
195
This is an example of a \emph{failing test}. The test says: if you
196
call \pythoninline{is\_divisible\_by\_2\_or\_5(8)} the result should
197
be \pythoninline{True}. Since 
198
\pythoninline{is\_divisible\_by\_2\_or\_5} as written doesn't return
199
anything at all, the test fails, and doctest tells us that it expected
200
\pythoninline{True} but got nothing.
201
202
We can make this test pass by returning True:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
203
204
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
205
\begin{python}
206
def is_divisible_by_2_or_5(n):
207
    """
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
208
    >>> is_divisible_by_2_or_5(8)
209
    True
1 by Brendan McCane
Initial import into bzr for version 2009
210
    """
211
    return True
212
213
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
214
if __name__ == "__main__":
1 by Brendan McCane
Initial import into bzr for version 2009
215
    import doctest
216
    doctest.testmod()
217
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
218
\end{minipage}
1 by Brendan McCane
Initial import into bzr for version 2009
219
220
If we run it now, there will be no output, which indicates that the
221
test passed. Note again that the doctest string must be placed
222
immediately after the function definition header in order to run. To
223
see more detailed output, add the keyword argument
224
\pythoninline{verbose=True} to the \pythoninline{testmod} method call
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
225
1 by Brendan McCane
Initial import into bzr for version 2009
226
\begin{python}
227
doctest.testmod(verbose=True)
228
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
229
1 by Brendan McCane
Initial import into bzr for version 2009
230
and run the module again.  This will produce output showing the result
231
of running the tests and whether they pass or not.
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
232
233
\begin{minipage}{\textwidth}
1 by Brendan McCane
Initial import into bzr for version 2009
234
\begin{pythonOutput}
235
Trying:
236
    is_divisible_by_2_or_5(8)
237
Expecting:
238
    True
239
ok
240
1 items had no tests:
241
    __main__
242
1 items passed all tests:
243
   1 tests in __main__.is_divisible_by_2_or_5
244
1 tests in 2 items.
245
1 passed and 0 failed.
246
Test passed.
247
\end{pythonOutput}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
248
\end{minipage}
1 by Brendan McCane
Initial import into bzr for version 2009
249
250
While the test passed, our test suite is clearly inadequate, since
251
\pythoninline{is\_divisible\_by\_2\_or\_5} will now return
252
\pythoninline{True} no matter what argument is passed to it. Here is a
253
completed version with a more complete test suite and code that makes
254
the tests pass:
255
256
\begin{minipage}{\textwidth}
257
\begin{python}
258
def is_divisible_by_2_or_5(n):
259
    """
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
260
    >>> is_divisible_by_2_or_5(8)
261
    True
262
    >>> is_divisible_by_2_or_5(7)
263
    False
264
    >>> is_divisible_by_2_or_5(5)
265
    True
266
    >>> is_divisible_by_2_or_5(9)
267
    False
1 by Brendan McCane
Initial import into bzr for version 2009
268
    """
269
    return n % 2 == 0 or n % 5 == 0 
270
271
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
272
if __name__ == "__main__":
1 by Brendan McCane
Initial import into bzr for version 2009
273
    import doctest
274
    doctest.testmod()
275
\end{python}
276
\end{minipage}
277
Run the module again and see what you get.
278
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
279
\section{Good Practice Development}
68 by Brendan McCane
Split up case study 2 into 2 lectures and added a little bit more to the first one. Also created a few new exercises.
280
\label{sec-good-practice}
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
281
The difficult part of programming, ironically, is not the programming part. The difficult part is the problem solving part. That is, deciding how to solve the problem at hand. Most programming problems can be solved by splitting the problem into smaller problems until you get to problems you can solve. Then you join up those smaller solutions to solve the larger problem. Of course, it is not always obvious to know how to split up a large problem and this is where experience and practice plays a key role. Nevertheless, here are some things you can try when presented with a problem you have no idea how to solve.
282
283
Try splitting the problem into two sub-problems, and progressively split each sub-problem until you know how to solve something. For example:
284
\begin{enumerate}
285
\item Count the number of ``the''s in a string.
286
\begin{enumerate}
287
\item split the string into separate words
288
\item count the number of words that are equal to ``the''
289
\begin{enumerate}
290
\item test if a single word equals ``the''
291
\item scan a list of words and keep count of those that equal ``the''
292
\end{enumerate}
293
\end{enumerate}
294
\end{enumerate}
295
296
Even if you don't know how to solve a given sub-problem, and you can't think of how to split it further, at least you have a better chance of discovering how to solve a simpler problem (either by asking someone, or asking Google for example).
297
298
There are also simple rules to follow when you are developing your own test cases. You should include:
299
\begin{itemize}
300
\item typical input
301
\item atypical input (e.g. input at the extreme edge of allowable input)
302
\item incorrect or invalid input
303
\item the simplest type of input (if that makes sense)
304
\item the most complicated type of input (if that makes sense)
305
\item enough tests so that each line of code is exercised at least once in your test set (this is called test coverage).
306
\end{itemize}
1 by Brendan McCane
Initial import into bzr for version 2009
307
308
\section{Test-driven development demonstrated}
309
310
At this point in the lecture, the lecturer will demonstrate how
311
test-driven development should be used. We will use the extension
312
exercise from Lecture \ref{lecture-fruity} as our example.
313
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
314
315
\section{Programming with style}
316
Readability is very important to programmers, since in practice
317
programs are read and modified far more often then they are
318
written. All the code examples in this book will be consistent with
319
the \emph{Python Enhancement Proposal 8} (PEP 8), a style guide
320
developed by the Python community.
321
We'll have more to say about style as our programs become more
322
complex, but a few pointers will be helpful already:
323
\begin{itemize}
324
\item use 4 spaces for indentation
325
\item imports should go at the top of the file
326
\item separate function definitions with two blank lines
327
\item keep function definitions together
57.1.28 by Nick Meek
Fixed Bug #1257101
328
\item keep top level statements, including function calls, together in the main routine
329
 of the program
59 by Brendan McCane
Reorganised tdd (moved some stuff to strings). Added a section on good practice development and testing. There probably could be more here, but it does get reinforced throughout the paper.
330
\item use Test-driven development to develop your programs (this is not part of PEP 8, but is more a philosophy of software development).
331
\end{itemize}
332
1 by Brendan McCane
Initial import into bzr for version 2009
333
\section{Glossary}
334
\begin{description}
335
\item[unit testing:]An automatic procedure used to validate that
336
  individual units of code are working properly. Python has doctest
337
  built in for this purpose.
4 by Brendan McCane
Have modified the order of the book a bit and changed a couple of sections around. In particular, moved strings part 1 to before files, which makes the files lecture more interesting.
338
\item[module:]A file containing Python definitions and statements
339
   intended for use in other Python programs. The contents of a module
340
   are made available to the other program by using the import
341
   statement.
342
\item[standard library:]A library is a collection of software used as
343
   tools in the development of other software. The standard library of
344
   a programming language is the set of such tools that are
345
   distributed with the core programming language. Python comes with
346
   an extensive standard library.
347
\item[import statement:]A statement which makes the objects contained
348
   in a module available for use. There are three forms for the import
349
   statement. Using a hypothetical module named \pythoninline{mymod} containing
350
   functions \pythoninline{f1} and \pythoninline{f2}, and variables
351
\pythoninline{v1} and \pythoninline{v2}, examples of these three 
352
   forms include:
353
\begin{python}
354
import mymod
355
\end{python}
356
and:
357
\begin{python}
358
from mymod import f1, f2, v1, v2
359
\end{python}
360
and:
361
\begin{python}
362
from mymod import *
363
\end{python}
364
\item[namespace:]A syntactic container providing a context for names
365
   so that the same name can reside in different namespaces without
366
   ambiguity. In Python, modules, classes, functions and methods all
367
   form namespaces.
368
\item[naming collision:]A situation in which two or more names in a
369
   given namespace cannot be unambiguously resolved. Using
370
\begin{python}
371
import mymodule
372
\end{python}
373
instead of
374
\begin{python}
375
from mymodule import *
376
\end{python}
377
prevents naming collisions.
378
379
\item[attribute:] A variable defined inside a module.  Module
380
  attributes are accessed by using the \myidx{dot operator} (.).
381
\item[dot operator:] The dot operator (.) permits access to
382
   attributes and functions of a module.
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
383
\item[docstring]A string constant on the first line of a function or
384
   module definition (and as we will see later, in class and method
385
   definitions as well). Docstrings provide a convenient way to
386
   associate documentation with code. Docstrings are also used by the
387
   doctest module for automated testing.
1 by Brendan McCane
Initial import into bzr for version 2009
388
\end{description}
389
390
\newpage
391
\section{Laboratory exercises}
392
All of the exercises below should be added to a file named
57.1.28 by Nick Meek
Fixed Bug #1257101
393
\myurl{doctest\_ex.py} that contains the following in the main routine:
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
394
1 by Brendan McCane
Initial import into bzr for version 2009
395
\begin{python}
16.1.7 by Brendan McCane
Changed as many single quotes to double quotes as I reasonably could. Thus allowing for copy and paste from the pdf and fixing bug #534819.
396
if __name__ == "__main__":
1 by Brendan McCane
Initial import into bzr for version 2009
397
    import doctest
398
    doctest.testmod(verbose=True)
399
\end{python}
400
401
After completing each exercise in turn, run the program to confirm
402
that the doctests for your new function pass.
403
\begin{enumerate}
404
\item Write a compare function that returns \pythoninline{1} if
405
\pythoninline{a $>$ b}, \pythoninline{0} if \pythoninline{a == b},
406
  and \pythoninline{-1} if \pythoninline{a $<$ b}.
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
407
1 by Brendan McCane
Initial import into bzr for version 2009
408
\begin{python}
409
def compare(a, b):
410
    """
23 by Brendan McCane
Working my way through updates on the book.
411
    Returns 1 if a>b, 0 if a equals b, and -1 if a<b
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
412
    >>> compare(5, 4)
413
    1
414
    >>> compare(7, 7)
415
    0
416
    >>> compare(2, 3)
417
    -1
418
    >>> compare(42, 1)
419
    1
1 by Brendan McCane
Initial import into bzr for version 2009
420
    """
421
    #  Your function body should begin here.
422
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
423
1 by Brendan McCane
Initial import into bzr for version 2009
424
Fill in the body of the function so the doctests pass.
425
\item Use incremental development to write a function called
426
hypotenuse that returns the length of the hypotenuse of a right
427
triangle given the lengths of the other two sides as parameters. Record
428
each stage of the incremental development process as you go.
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
429
1 by Brendan McCane
Initial import into bzr for version 2009
430
\begin{python}
431
def hypotenuse(a, b):
432
    """
23 by Brendan McCane
Working my way through updates on the book.
433
    Compute the hypotenuse of a right triangle with sides of length a
434
    and b.
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
435
    >>> hypotenuse(3, 4)
436
    5.0
437
    >>> hypotenuse(12, 5)
438
    13.0
439
    >>> hypotenuse(7, 24)
440
    25.0
441
    >>> hypotenuse(9, 12)
442
    15.0
1 by Brendan McCane
Initial import into bzr for version 2009
443
    """
444
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
445
1 by Brendan McCane
Initial import into bzr for version 2009
446
When you are finished add your completed function with the doctests to
447
\myurl{doctest\_ex.py} and confirm that the doctests pass.
448
89 by Brendan McCane
Updated for 2017.
449
\checkpoint
450
1 by Brendan McCane
Initial import into bzr for version 2009
451
\item Write a body for the function definition of
452
\pythoninline{fahrenheit\_to\_celsius}
453
designed to return 
454
the integer value of the nearest degree Celsius for a given temperature
455
in Fahrenheit. Use your favourite web search engine to find the
456
equation for doing the conversion if you don't already know it.
30 by mccane at ac
Done corrections3 from Matthew.
457
(\emph{Hint:} you may want to make use of the built-in
1 by Brendan McCane
Initial import into bzr for version 2009
458
function, \pythoninline{round}. Try typing \pythoninline{help(round)}
459
in a Python 
460
shell and experimenting with round until you are comfortable with how
461
it works.)
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
462
1 by Brendan McCane
Initial import into bzr for version 2009
463
\begin{python}
464
def fahrenheit_to_celsius(t):
465
    """
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
466
    >>> fahrenheit_to_celsius(212)
467
    100
468
    >>> fahrenheit_to_celsius(32)
469
    0
470
    >>> fahrenheit_to_celsius(-40)
471
    -40
472
    >>> fahrenheit_to_celsius(36)
473
    2
474
    >>> fahrenheit_to_celsius(37)
475
    3
476
    >>> fahrenheit_to_celsius(38)
477
    3
478
    >>> fahrenheit_to_celsius(39)
479
    4
1 by Brendan McCane
Initial import into bzr for version 2009
480
    """
481
\end{python}
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
482
1 by Brendan McCane
Initial import into bzr for version 2009
483
\item Add a function body for \pythoninline{celsius\_to\_fahrenheit}
484
to convert from Celsius to Fahrenheit. 
11 by Brendan McCane
Everything up to case_study_catch.tex should be in pretty good shape now. I am in the process of going through catch1 and catch2 and adding docstrings at the start of each class. Also still need to add in some extension exercises (maybe into the gui intro too).
485
1 by Brendan McCane
Initial import into bzr for version 2009
486
\begin{python}
487
def celsius_to_fahrenheit(t):
488
    """
16.1.1 by Brendan McCane
Fixed up the misaligned tests problem.
489
    >>> celsius_to_fahrenheit(0)
490
    32
491
    >>> celsius_to_fahrenheit(100)
492
    212
493
    >>> celsius_to_fahrenheit(-40)
494
    -40
495
    >>> celsius_to_fahrenheit(12)
496
    54
497
    >>> celsius_to_fahrenheit(18)
498
    64
499
    >>> celsius_to_fahrenheit(-48)
500
    -54
1 by Brendan McCane
Initial import into bzr for version 2009
501
    """
502
\end{python}
3 by Brendan McCane
Have made some fairly minor modifications for 2010.
503
39 by Brendan McCane
Still working through all these updates.
504
\item \emph{Extension Exercise:} Write a function to convert kilograms
505
  to pounds. Devise a sensible test suite for your function.
506
507
\item \emph{Extension Exercise:} Write a function that takes the
508
  width, height and depth of a cuboid and returns its surface area. It
509
  should return -1 if an argument is negative. Devise a sensible test
510
  suite for your function. 
511
52 by mccane at ac
Some changes.
512
\begin{minipage}{\textwidth}
39 by Brendan McCane
Still working through all these updates.
513
\item \emph{Extension Exercise:} Write a function that returns the
514
  volume of a square based pyramid. It should take as arguments the
515
  length of a bottom edge and the height. It should return -1 if
516
  either parameter is less than 0. Your function should pass the
517
  doctests below. 
518
519
\begin{python}
520
def vol_of_a_pyramid(edge, height):
521
    """
522
    >>> vol_of_a_pyramid(0, 3)
523
    0.0
524
    >>> vol_of_a_pyramid(3, 0)
525
    0.0
526
    >>> vol_of_a_pyramid(2, 3)
527
    4.0
528
    >>> vol_of_a_pyramid(4, 3)
529
    16.0
530
    >>> vol_of_a_pyramid(6, 4)
531
    48.0
532
    >>> vol_of_a_pyramid(5, 4.5)
533
    37.5
534
    >>> vol_of_a_pyramid(-2, 4)
535
    -1
536
    >>> vol_of_a_pyramid(2, -4)
537
    -1
538
    """
539
\end{python}
52 by mccane at ac
Some changes.
540
\end{minipage}
39 by Brendan McCane
Still working through all these updates.
541
1 by Brendan McCane
Initial import into bzr for version 2009
542
\end{enumerate}
543
544
\submitreminder