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
|