-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy paththink-python.html
More file actions
961 lines (904 loc) · 79.6 KB
/
think-python.html
File metadata and controls
961 lines (904 loc) · 79.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="author" content="Matthew X. Curinga">
<meta name="author" content="Peter Wentworth">
<meta name="author" content="Jeffrey Elkner">
<meta name="author" content="Allen B. Downey">
<meta name="author" content="and Chris Meyers">
<title>How to Think Like a Computer Scientist</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
</style>
<!-- this css file gets inlined by the build script to make standalone html5 output
that is why it has a style tag... -->
<style type="text/css">
body
{
background-color: white;
margin: 0;
padding: 0;
font-size: 14px;
}
body, p, ul, ol, li, span, div
{
font-family: "FreeSans", "Helvetica", sans-serif;
}
pre, code, tt, code span, pre span
{
font-family: "DejaVu Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
}
aside
{
border: medium solid gray;
border-radius: 8px;
padding: .5em;
margin: 3em .5em;
background-color: #F6CCDA;
}
h1,h2,h3,h4,h5 { font-family: Ubuntu, "Gotham", "Futura", "Century Gothic", sans-serif; }
h1{ font-size: 150%; margin: 0px; margin-top: 2em; }
h2{ font-size: 130%; margin:0; margin-top: 1em; text-transform: uppercase;}
h3{ font-size: 120%; font-weight: bold; }
h4{ font-size: 110%; font-weight: bold; }
h5 { padding: 0; margin: 0; font-size: 100%; font-style: italic; }
h1.title
{
margin:0;
padding:0;
padding-top: 80px;
border-style: none;
background-color: transparent;
color: black;
clear: both;
font-size: 200%;
font-weight: bold;
color: #ab1c19;
}
pre
{
border: thin solid gray;
background: #ededed;
padding: .5em;
}
dl { margin-left: 2em; }
dt
{
font-weight: bold;
font-size: 115%;
margin-top: .5em;
}
dd p {padding: 0; margin: 0; }
a { text-decoration: none; }
a img { border-style: none; }
tr.odd { background-color: #d3d3d3; }
p
{
margin: .5em 0;
line-height: 1.5em;
}
blockquote
{
line-height: 120%;
font-size: 90%;
border-left: 3px solid gray;
padding-left: 1em;
}
@media screen
{
body
{
font-size: 14px;
width: 900px;
margin: 0 auto;
}
}
nav#TOC
{
background: none repeat scroll 0 0 white;
border: 1px solid black;
counter-reset: toc;
margin: 1.5em;
}
nav#TOC li
{
list-style: none;
}
#TOC h3 { text-align: center; }
/** code highlighting stuff **/
table.sourceCode, pre.sourceCode
{
width: 90%;
margin: 0 auto;
line-height: 1.15em;
}
td.lineNumbers {
border-right: 0px none;
padding-right: 0px;
margin-right: 0px;
width: 2em;
text-align: right;
}
</style>
</head>
<body>
<header>
<h1 class="title">How to Think Like a Computer Scientist</h1>
<h2 class="author">Matthew X. Curinga</h2>
<h2 class="author">Peter Wentworth</h2>
<h2 class="author">Jeffrey Elkner</h2>
<h2 class="author">Allen B. Downey</h2>
<h2 class="author">and Chris Meyers</h2>
</header>
<nav id="TOC">
<ul>
<li><a href="#copyright-notice"><span class="toc-section-number">1</span> Copyright Notice</a></li>
<li><a href="#foreword"><span class="toc-section-number">2</span> Foreword</a></li>
<li><a href="#preface"><span class="toc-section-number">3</span> Preface</a><ul>
<li><a href="#how-and-why-i-came-to-use-python"><span class="toc-section-number">3.1</span> How and why I came to use Python</a></li>
<li><a href="#finding-a-textbook"><span class="toc-section-number">3.2</span> Finding a textbook</a></li>
<li><a href="#introducing-programming-with-python"><span class="toc-section-number">3.3</span> Introducing programming with Python</a></li>
<li><a href="#building-a-community"><span class="toc-section-number">3.4</span> Building a community</a></li>
</ul></li>
<li><a href="#the-rhodes-local-edition-rle-version-of-august-2012"><span class="toc-section-number">4</span> The Rhodes Local Edition (RLE) (Version of August, 2012)</a></li>
<li><a href="#functions"><span class="toc-section-number">5</span> Functions</a><ul>
<li><a href="#functions-1"><span class="toc-section-number">5.1</span> Functions</a></li>
<li><a href="#composition-functions-can-call-other-functions"><span class="toc-section-number">5.2</span> Composition: Functions can call other functions</a></li>
<li><a href="#flow-of-execution"><span class="toc-section-number">5.3</span> Flow of execution</a></li>
<li><a href="#functions-that-require-arguments"><span class="toc-section-number">5.4</span> Functions that require arguments</a></li>
<li><a href="#functions-that-return-values"><span class="toc-section-number">5.5</span> Functions that return values</a></li>
<li><a href="#tips-revisited"><span class="toc-section-number">5.6</span> Tips Revisited</a></li>
<li><a href="#glossary"><span class="toc-section-number">5.7</span> Glossary</a></li>
<li><a href="#exercises"><span class="toc-section-number">5.8</span> Exercises</a></li>
</ul></li>
<li><a href="#contributor-list"><span class="toc-section-number">6</span> Contributor List</a><ul>
<li><a href="#second-edition"><span class="toc-section-number">6.1</span> Second Edition</a></li>
<li><a href="#first-edition"><span class="toc-section-number">6.2</span> First Edition</a></li>
</ul></li>
</ul>
</nav>
<p><strong>Adelphi University Mod</strong><br />based on the <em>Learning with Python 3 (RLE)</em> by Peter Wentworth</p>
<section class="level1" id="copyright-notice">
<h1><a href="#copyright-notice"><span class="header-section-number">1</span> Copyright Notice</a></h1>
<p>Copyright (C) Peter Wentworth.</p>
<p>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with Invariant Sections being Foreword, Preface, and Contributor List, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.</p>
</section>
<section class="level1" id="foreword">
<h1><a href="#foreword"><span class="header-section-number">2</span> Foreword</a></h1>
<p>By David Beazley</p>
<p>As an educator, researcher, and book author, I am delighted to see the completion of this book. Python is a fun and extremely easy-to-use programming language that has steadily gained in popularity over the last few years. Developed over ten years ago by Guido van Rossum, Python’s simple syntax and overall feel is largely derived from ABC, a teaching language that was developed in the 1980’s. However, Python was also created to solve real problems and it borrows a wide variety of features from programming languages such as C++, Java, Modula-3, and Scheme. Because of this, one of Python’s most remarkable features is its broad appeal to professional software developers, scientists, researchers, artists, and educators.</p>
<p>Despite Python’s appeal to many different communities, you may still wonder why Python? or why teach programming with Python? Answering these questions is no simple task—especially when popular opinion is on the side of more masochistic alternatives such as C++ and Java. However, I think the most direct answer is that programming in Python is simply a lot of fun and more productive.</p>
<p>When I teach computer science courses, I want to cover important concepts in addition to making the material interesting and engaging to students. Unfortunately, there is a tendency for introductory programming courses to focus far too much attention on mathematical abstraction and for students to become frustrated with annoying problems related to low-level details of syntax, compilation, and the enforcement of seemingly arcane rules. Although such abstraction and formalism is important to professional software engineers and students who plan to continue their study of computer science, taking such an approach in an introductory course mostly succeeds in making computer science boring. When I teach a course, I don’t want to have a room of uninspired students. I would much rather see them trying to solve interesting problems by exploring different ideas, taking unconventional approaches, breaking the rules, and learning from their mistakes. In doing so, I don’t want to waste half of the semester trying to sort out obscure syntax problems, unintelligible compiler error messages, or the several hundred ways that a program might generate a general protection fault.</p>
<p>One of the reasons why I like Python is that it provides a really nice balance between the practical and the conceptual. Since Python is interpreted, beginners can pick up the language and start doing neat things almost immediately without getting lost in the problems of compilation and linking. Furthermore, Python comes with a large library of modules that can be used to do all sorts of tasks ranging from web-programming to graphics. Having such a practical focus is a great way to engage students and it allows them to complete significant projects. However, Python can also serve as an excellent foundation for introducing important computer science concepts. Since Python fully supports procedures and classes, students can be gradually introduced to topics such as procedural abstraction, data structures, and object-oriented programming — all of which are applicable to later courses on Java or C++. Python even borrows a number of features from functional programming languages and can be used to introduce concepts that would be covered in more detail in courses on Scheme and Lisp.</p>
<p>In reading Jeffrey’s preface, I am struck by his comments that Python allowed him to see a higher level of success and a lower level of frustration and that he was able to move faster with better results. Although these comments refer to his introductory course, I sometimes use Python for these exact same reasons in advanced graduate level computer science courses at the University of Chicago. In these courses, I am constantly faced with the daunting task of covering a lot of difficult course material in a blistering nine week quarter. Although it is certainly possible for me to inflict a lot of pain and suffering by using a language like C++, I have often found this approach to be counterproductive—especially when the course is about a topic unrelated to just programming. I find that using Python allows me to better focus on the actual topic at hand while allowing students to complete substantial class projects.</p>
<p>Although Python is still a young and evolving language, I believe that it has a bright future in education. This book is an important step in that direction. David Beazley University of Chicago Author of the <em>Python Essential Reference</em></p>
</section>
<section class="level1" id="preface">
<h1><a href="#preface"><span class="header-section-number">3</span> Preface</a></h1>
<p>By Jeffrey Elkner</p>
<p>This book owes its existence to the collaboration made possible by the Internet and the free software movement. Its three authors—a college professor, a high school teacher, and a professional programmer—never met face to face to work on it, but we have been able to collaborate closely, aided by many other folks who have taken the time and energy to send us their feedback.</p>
<p>We think this book is a testament to the benefits and future possibilities of this kind of collaboration, the framework for which has been put in place by Richard Stallman and the Free Software Foundation.</p>
<section class="level2" id="how-and-why-i-came-to-use-python">
<h2><a href="#how-and-why-i-came-to-use-python"><span class="header-section-number">3.1</span> How and why I came to use Python</a></h2>
<p>In 1999, the College Board’s Advanced Placement (AP) Computer Science exam was given in C++ for the first time. As in many high schools throughout the country, the decision to change languages had a direct impact on the computer science curriculum at Yorktown High School in Arlington, Virginia, where I teach. Up to this point, Pascal was the language of instruction in both our first-year and AP courses. In keeping with past practice of giving students two years of exposure to the same language, we made the decision to switch to C++ in the first year course for the 1997-98 school year so that we would be in step with the College Board’s change for the AP course the following year.</p>
<p>Two years later, I was convinced that C++ was a poor choice to use for introducing students to computer science. While it is certainly a very powerful programming language, it is also an extremely difficult language to learn and teach. I found myself constantly fighting with C++’s difficult syntax and multiple ways of doing things, and I was losing many students unnecessarily as a result. Convinced there had to be a better language choice for our first-year class, I went looking for an alternative to C++.</p>
<p>I needed a language that would run on the machines in our GNU/Linux lab as well as on the Windows and Macintosh platforms most students have at home. I wanted it to be free software, so that students could use it at home regardless of their income. I wanted a language that was used by professional programmers, and one that had an active developer community around it. It had to support both procedural and object-oriented programming. And most importantly, it had to be easy to learn and teach. When I investigated the choices with these goals in mind, Python stood out as the best candidate for the job.</p>
<p>I asked one of Yorktown’s talented students, Matt Ahrens, to give Python a try. In two months he not only learned the language but wrote an application called pyTicket that enabled our staff to report technology problems via the Web. I knew that Matt could not have finished an application of that scale in so short a time in C++, and this accomplishment, combined with Matt’s positive assessment of Python, suggested that Python was the solution I was looking for.</p>
</section>
<section class="level2" id="finding-a-textbook">
<h2><a href="#finding-a-textbook"><span class="header-section-number">3.2</span> Finding a textbook</a></h2>
<p>Having decided to use Python in both of my introductory computer science classes the following year, the most pressing problem was the lack of an available textbook.</p>
<p>Free documents came to the rescue. Earlier in the year, Richard Stallman had introduced me to Allen Downey. Both of us had written to Richard expressing an interest in developing free educational materials. Allen had already written a first-year computer science textbook, <em>How to Think Like a Computer Scientist</em>. When I read this book, I knew immediately that I wanted to use it in my class. It was the clearest and most helpful computer science text I had seen. It emphasized the processes of thought involved in programming rather than the features of a particular language. Reading it immediately made me a better teacher.</p>
<p><em>How to Think Like a Computer Scientist</em> was not just an excellent book, but it had been released under the GNU public license, which meant it could be used freely and modified to meet the needs of its user. Once I decided to use Python, it occurred to me that I could translate Allen’s original Java version of the book into the new language. While I would not have been able to write a textbook on my own, having Allen’s book to work from made it possible for me to do so, at the same time demonstrating that the cooperative development model used so well in software could also work for educational materials.</p>
<p>Working on this book for the last two years has been rewarding for both my students and me, and my students played a big part in the process. Since I could make instant changes whenever someone found a spelling error or difficult passage, I encouraged them to look for mistakes in the book by giving them a bonus point each time they made a suggestion that resulted in a change in the text. This had the double benefit of encouraging them to read the text more carefully and of getting the text thoroughly reviewed by its most important critics, students using it to learn computer science.</p>
<p>For the second half of the book on object-oriented programming, I knew that someone with more real programming experience than I had would be needed to do it right. The book sat in an unfinished state for the better part of a year until the open source community once again provided the needed means for its completion.</p>
<p>I received an email from Chris Meyers expressing interest in the book. Chris is a professional programmer who started teaching a programming course last year using Python at Lane Community College in Eugene, Oregon. The prospect of teaching the course had led Chris to the book, and he started helping out with it immediately. By the end of the school year he had created a companion project on our Website at <a href="http://openbookproject.net">http://openbookproject.net</a> (<em>Python for Fun</em>)[http://openbookproject.net/py4fun>] and was working with some of my most advanced students as a master teacher, guiding them beyond where I could take them.</p>
</section>
<section class="level2" id="introducing-programming-with-python">
<h2><a href="#introducing-programming-with-python"><span class="header-section-number">3.3</span> Introducing programming with Python</a></h2>
<p>The process of translating and using <em>How to Think Like a Computer Scientist</em> for the past two years has confirmed Python’s suitability for teaching beginning students. Python greatly simplifies programming examples and makes important programming ideas easier to teach.</p>
<p>The first example from the text illustrates this point. It is the traditional hello, world program, which in the Java version of the book looks like this:</p>
<pre class="sourceCode java"><code class="sourceCode java"><span class="kw">class</span> Hello
{
<span class="kw">public</span> <span class="dt">static</span> <span class="dt">void</span> <span class="fu">main</span> (String[] args)
{
System.<span class="fu">out</span>.<span class="fu">println</span> (<span class="st">"Hello, world."</span>);
}
}</code></pre>
<p>in the Python version it becomes:</p>
<pre class="sourceCode python"><code class="sourceCode python"><span class="kw">print</span>(<span class="st">"Hello, World!"</span>)</code></pre>
<p>Even though this is a trivial example, the advantages of Python stand out. Yorktown’s Computer Science I course has no prerequisites, so many of the students seeing this example are looking at their first program. Some of them are undoubtedly a little nervous, having heard that computer programming is difficult to learn. The Java version has always forced me to choose between two unsatisfying options: either to explain the <code>class Hello</code>, <code>public static void main</code>, <code>String[] args</code>, <code>{</code>, and <code>}</code>, statements and risk confusing or intimidating some of the students right at the start, or to tell them, Just don’t worry about all of that stuff now; we will talk about it later, and risk the same thing. The educational objectives at this point in the course are to introduce students to the idea of a programming statement and to get them to write their first program, thereby introducing them to the programming environment. The Python program has exactly what is needed to do these things, and nothing more.</p>
<p>Comparing the explanatory text of the program in each version of the book further illustrates what this means to the beginning student. There are seven paragraphs of explanation of Hello, world! in the Java version; in the Python version, there are only a few sentences. More importantly, the missing six paragraphs do not deal with the big ideas in computer programming but with the minutia of Java syntax. I found this same thing happening throughout the book. Whole paragraphs simply disappear from the Python version of the text because Python’s much clearer syntax renders them unnecessary.</p>
<p>Using a very high-level language like Python allows a teacher to postpone talking about low-level details of the machine until students have the background that they need to better make sense of the details. It thus creates the ability to put first things first pedagogically. One of the best examples of this is the way in which Python handles variables. In Java a variable is a name for a place that holds a value if it is a built-in type, and a reference to an object if it is not. Explaining this distinction requires a discussion of how the computer stores data. Thus, the idea of a variable is bound up with the hardware of the machine. The powerful and fundamental concept of a variable is already difficult enough for beginning students (in both computer science and algebra). Bytes and addresses do not help the matter. In Python a variable is a name that refers to a thing. This is a far more intuitive concept for beginning students and is much closer to the meaning of variable that they learned in their math courses. I had much less difficulty teaching variables this year than I did in the past, and I spent less time helping students with problems using them.</p>
<p>Another example of how Python aids in the teaching and learning of programming is in its syntax for functions. My students have always had a great deal of difficulty understanding functions. The main problem centers around the difference between a function definition and a function call, and the related distinction between a parameter and an argument. Python comes to the rescue with syntax that is nothing short of beautiful. Function definitions begin with the keyword <code>def</code>, so I simply tell my students, When you define a function, begin with <code>def</code>, followed by the name of the function that you are defining; when you call a function, simply call (type) out its name. Parameters go with definitions; arguments go with calls. There are no return types, parameter types, or reference and value parameters to get in the way, so I am now able to teach functions in less than half the time that it previously took me, with better comprehension.</p>
<p>Using Python improved the effectiveness of our computer science program for all students. I saw a higher general level of success and a lower level of frustration than I experienced teaching with either C++ or Java. I moved faster with better results. More students left the course with the ability to create meaningful programs and with the positive attitude toward the experience of programming that this engenders.</p>
</section>
<section class="level2" id="building-a-community">
<h2><a href="#building-a-community"><span class="header-section-number">3.4</span> Building a community</a></h2>
<p>I have received email from all over the globe from people using this book to learn or to teach programming. A user community has begun to emerge, and many people have been contributing to the project by sending in materials for the companion Website at <a href="http://openbookproject.net/pybiblio">http://openbookproject.net/pybiblio</a>.</p>
<p><strong>With the continued growth of Python, I expect the growth in the user community to continue and accelerate. The emergence of this user community and the possibility it suggests for similar collaboration among educators have been the most exciting parts of working on this project for me. By working together, we can increase the quality of materials available for our use and save valuable time. I invite you to join our community and look forward to hearing from you. Please write to me at <script type="text/javascript">
<!--
h='elkner.net>';a='@';n='jeff';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'">'+'jeff@elkner.net'+'<\/'+'a'+'>');
// -->
</script><noscript>jeff@elkner.net (jeff at elkner dot net>)</noscript></strong>.</p>
<p>Jeffrey Elkner<br />Governor’s Career and Technical Academy in Arlington<br />Arlington, Virginia<br /></p>
</section>
</section>
<section class="level1" id="the-rhodes-local-edition-rle-version-of-august-2012">
<h1><a href="#the-rhodes-local-edition-rle-version-of-august-2012"><span class="header-section-number">4</span> The Rhodes Local Edition (RLE) (Version of August, 2012)</a></h1>
<p>By Peter Wentworth</p>
<aside>
<p><strong>A word of thanks …</strong></p>
<p>We switched from Java to Python in our introductory courses in 2010. So far we think the results look positive. More time will tell.</p>
<p>This predecessor to this book was a great starting point for us, especially because of the liberal permission to change things. Having our own in-house course notes or handouts allows us to adapt and stay fresh, rearrange, see what works, and it gives us agility. We can also ensure that every student in the course gets a copy of the handouts — something that doesn’t always happen if we prescribe costly textbooks.</p>
Many thanks to all the contributors and the authors for making their hard work available to the Python community and to our students.
</aside>
<p>A colleague and friend, Peter Warren, once made the remark that learning introductory programming is as much about the environment as it is about the programming language.</p>
<p>I’m a big fan of IDEs (Integrated Development Environments).<br />I want help to be integrated into my editor, as a first-class citizen, available at the press of a button. I want syntax highlighting. I want immediate syntax checking, and sensible autocompletion. I’d like an editor that can fold function bodies or regions of code away, because it promotes and encourages how we build mental abstractions.</p>
<p>I’m especially keen on having a single-stepping debugger and breakpoints with code inspection built in. We’re trying to build a conceptual model of program execution in the student’s mind, so I find most helpful for teaching to have the call stack and variables explicitly visible, and to be able to immediately inspect the result of executing a statement.</p>
<p>My philosophy, then, is not to look for a language to teach, but to look for a combination of IDE and language that are packaged together, and evaluated as a whole.</p>
<p>I’ve made some quite deep changes to the original book to reflect this (and various other opinionated views that I hold), and I have no doubt that more changes will follow as we mature our course.</p>
<p>Here are some of the key things I’ve approached differently:</p>
<ul>
<li>Our local situation demands that we have a large number of service course students in an introductory course of just 3 weeks, and then we get another semester of teaching with those going into our mainstream program. So the book is in two parts: we’ll do the first five chapters in the big “get your toes wet” course, and the rest of the material in a separate semester.</li>
<li>We’re using Python 3. It is cleaner, more object oriented, and has fewer ad-hoc irregularities than earlier versions of Python.</li>
<li>We’re using PyScripter as our IDE, on Windows. And it is hardwired into parts of these notes, with screenshots, etc.</li>
<li>I’ve dropped GASP.</li>
<li>For graphics we start with the Turtle module.<br /> As things move along, we use PyGame for more advanced graphics.</li>
<li>I’ve introduced some event-driven programming using the turtle.<br /></li>
<li>I have tried to push more object-oriented notions earlier, without asking students to synthesize objects or write their own classes. So, for example, in the chapter about the turtle, we create multiple instances of turtles, talk about their attributes and state (color, position, etc), and we favour method-call style to move them around, i.e. <code>tess.forward(100)</code>. Similarly, when we use random numbers, we avoid the “hidden singleton generator” in the random module — we prefer to create an instance of a generator, and invoke methods on the instance.</li>
<li>The ease of constructing lists and the <code>for</code> loop seem to be winners in Python, so rather than use the traditional command-line <code>input</code> for data, I’ve favoured using loops and lists right up front, like this:</li>
</ul>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
</pre></td><td class="sourceCode"><pre><code class="sourceCode python">friends = [<span class="st">"Zoe"</span>, <span class="st">"Joe"</span>, <span class="st">"Bill"</span>]
<span class="kw">for</span> f in friends:
invitation = <span class="st">"Hi "</span> + f + <span class="st">". Please come to my party on Saturday!"</span>
<span class="kw">print</span>(invitation)</code></pre></td></tr></table>
<p>This also means that I bumped <code>range</code> up for early exposure.<br />I envisage that over time we’ll see more opportunities to exploit “early lists, early iteration” in its most simple form.</p>
<ul>
<li>I dumped <code>doctest</code>: it is too quirky for my liking. For example, it fails a test if the spacing between list elements is not precisely the same as the output string, or if Python prints a string with single quotes, but you wrote up the test case with double quotes. Cases like this also confused students (and instructors) quite badly:</li>
</ul>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="sourceCode"><pre><code class="sourceCode python">
<span class="kw">def</span> addlist(xs):
<span class="co">"""</span>
<span class="co"> >>> xs = [2,3,4]</span>
<span class="co"> >>> addlist(xs)</span>
<span class="co"> 9</span>
<span class="co"> """</span>
<span class="kw">return</span></code></pre></td></tr></table>
<p>If you can explain the difference in scope rules and lifetimes between the parameter <code>xs</code> and the doctest variable <code>xs</code> elegantly, please let me know. Yes, I know doctest creates its own scope behind our back, but it is exactly this black magic that we’re trying to avoid.<br />From the usual indentation rules, also looks like the doctests are nested inside the function scope, but they are not. Students thought that the parameter had been given its value by the assignment to <code>xs</code> in the doctest!</p>
<p>I also think that keeping the test suite separate from the functions under test leads to a cleaner relationship between caller and callee, and gives a better chance of getting argument passing / parameter concepts taught accurately.</p>
<p>There is a good unit testing module in Python, (and PyScripter offers integrated support for it, and automated generation of skeleton test modules), but it looked too advanced for beginners, because it requires multi-module concepts.</p>
<p>So I’ve favoured my own test scaffolding in Chapter 6 (about 10 lines of code) that the students must insert into whatever file they’re working on.</p>
<ul>
<li><p>I’ve played down command-line input / process / output where possible. Many of our students have never seen a command-line shell, and it is arguably quite intimidating.</p></li>
<li><p>We’ve gone back to a more “classic / static” approach to writing our own classes and objects. Python (in company with languages like Javascript, Ruby, Perl, PHP, etc.) don’t really emphasize notions of “sealed” classes or “private” members, or even “sealed instances”.</p></li>
</ul>
<p>So one teaching approach is to allocate each instance as an empty container, and subsequently allow the external clients of the class to poke new members (methods or attributes) into different instances as they wish to.<br /> It is a very dynamic approach, but perhaps not one that encourages thinking in abstractions, layers, contracts, decoupling, etc. It might even be the kind of thing that one could write one of those <em>“x,y,z … considered harmful”</em> papers about.</p>
<p>In our more conservative approach, we put an initializer into every class, we determine at object instantiation time what members we want, and we initialize the instances from within the class. So we’ve moved closer in philosophy to C# / Java on this one.</p>
<ul>
<li><p>We’re moving towards introducing more algorithms earlier into the course. Python is an efficient teaching language — we can make fast progress. But the gains we make there we’d like to invest into deeper problem solving, and more complex algorithms with the basics, rather than cover “more Python features”. Some of these changes have started to find their way in this version, and I’m sure we’ll see more in future.</p></li>
<li><p>We’re interested in issues around teaching and learning. Some research indicates that “intellectual playfulness” is important. The study referenced in the Odds-and-ends workbook at the end just didn’t seem to have anywhere sensible to go in the book, yet I wanted it included. It is quite likely that we’ll allow more issues like this to creep into the book, to try to make it more than just about programming in Python.</p></li>
</ul>
</section>
<section class="level1" id="functions">
<h1><a href="#functions"><span class="header-section-number">5</span> Functions</a></h1>
<section class="level2" id="functions-1">
<h2><a href="#functions-1"><span class="header-section-number">5.1</span> Functions</a></h2>
<p>In Python, a <strong>function</strong> is a named sequence of statements that belong together. Their primary purpose is to help us organize programs into chunks that match how we think about the problem.</p>
<p>The syntax for a <strong>function definition</strong> is:</p>
<pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> NAME( PARAMETERS ):
STATEMENTS</code></pre>
<p>We can make up any names we want for the functions we create, except that we can’t use a name that is a Python keyword, and the names must follow the rules for legal identifiers.</p>
<p>There can be any number of statements inside the function, but they have to be indented from the <code>def</code>. In the examples in this book, we will use the standard indentation of four spaces. Function definitions are the second of several <strong>compound statements</strong> we will see, all of which have the same pattern:</p>
<ol type="1">
<li>A header line which begins with a keyword and ends with a colon.</li>
<li>A <strong>body</strong> consisting of one or more Python statements, each indented the same amount — <em>the Python style guide recommends 4 spaces</em> — from the header line.</li>
</ol>
<p>We’ve already seen the <code>for</code> loop which follows this pattern.</p>
<p>So looking again at the function definition, the keyword in the header is <code>def</code>, which is followed by the name of the function and some <em>parameters</em> enclosed in parentheses. The parameter list may be empty, or it may contain any number of parameters separated from one another by commas. In either case, the parentheses are required. The parameters specifies what information, if any, we have to provide in order to use the new function.</p>
<p>Suppose we’re working with turtles, and a common operation we need is to draw squares. “Draw a square” is an <em>abstraction</em>, or a mental chunk, of a number of smaller steps. So let’s write a function to capture the pattern of this “building block”:</p>
<p>Suppose we are writing a program to calculate the amount of tip due on a bill. We might write a function to “calculate tip”. “calculate tip” is an <em>abstraction</em>, or a mental chunk, of a number of smaller steps. So let’s write a function to capture the pattern of this “building block”:</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> calculate_tip(bill, pct):
<span class="co">"""</span>
<span class="co"> Calculate the tip on a bill, given the pct of the tip.</span>
<span class="co"> """</span>
tip = bill * (pct * .<span class="dv">01</span>) <span class="co"># convert pct to a decimal and calculate</span>
tip = <span class="dt">round</span>(tip, <span class="dv">2</span>) <span class="co"># round the tip to 2 decimal places</span>
total = tip + bill
<span class="co"># now show the results to the user</span>
<span class="kw">print</span>(<span class="st">"Bill total: $"</span> + <span class="dt">str</span>(bill))
<span class="kw">print</span>(<span class="st">"Tip percentage: "</span> + <span class="dt">str</span>(pct) + <span class="st">"%"</span>)
<span class="kw">print</span>(<span class="st">"Tip amount due: $"</span> + <span class="dt">str</span>(total))
<span class="co"># find the amount of an 18% tip on a $100 bill</span>
calculate_tip(<span class="dv">100</span>,<span class="dv">18</span>)</code></pre></td></tr></table>
<aside id="docstrings">
<p><strong>Docstrings for documentation</strong></p>
<p>If the first thing after the function header is a string, it is treated as a <strong>docstring</strong> and gets special treatment in Python and in some programming tools. For example, when we type a built-in function name with an unclosed parenthesis in PyScripter, a tooltip pops up, telling us what arguments the function takes, and it shows us any other text contained in the docstring.</p>
<p>Docstrings are the key way to document our functions in Python and the documentation part is important. Because whoever calls our function shouldn’t have to need to know what is going on in the function or how it works; they just need to know what arguments our function takes, what it does, and what the expected result is. Enough to be able to use the function without having to look underneath. This goes back to the concept of abstraction of which we’ll talk more about.</p>
<p>Docstrings are usually formed using triple-quoted strings as they allow us to easily expand the docstring later on should we want to write more than a one-liner.</p>
Just to differentiate from comments, a string at the start of a function (a docstring) is retrievable by Python tools <em>at runtime</em>. By contrast, comments are completely eliminated when the program is parsed.
</aside>
<p>This function is named <code>calculate_tip</code>. It has two parameters: one to tell the function the amount of the bill, and the other to tell it the percent tip to calculate. Make sure you know where the body of the function ends — it depends on the indentation, and the blank lines don’t count for this purpose!</p>
<p>Defining a new function does not make the function run. To do that we need a <strong>function call</strong>. We’ve already seen how to call some built-in functions like <strong>print</strong>, <strong>range</strong>, <strong>round</strong>, and <strong>int</strong>. Function calls contain the name of the function being executed followed by a list of values, called <em>arguments</em>, which are assigned to the parameters in the function definition. So in the last line of the example program above, we call the function, and pass <code>100</code> as the amount of the bill and <code>18</code> as the percentage of the tip. While the function is executing, then, the variable <code>bill</code> refers to the value 100, and the variable <code>pct</code> refers to 18.</p>
<p>Once we’ve defined a function, we can call it as often as we like, and its statements will be executed each time we call it. And we could use it to get any of our turtles to draw a square. In the next example, we calculate 3 different tip amounts for the same bill.</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> calculate_tip(bill, pct):
<span class="co">"""</span>
<span class="co"> Calculate the tip on a bill, given the pct of the tip.</span>
<span class="co"> """</span>
tip = bill * (pct * .<span class="dv">01</span>) <span class="co"># convert pct to a decimal and calculate</span>
tip = <span class="dt">round</span>(tip, <span class="dv">2</span>) <span class="co"># round the tip to 2 decimal places</span>
total = tip + bill
<span class="co"># now show the results to the user</span>
<span class="kw">print</span>(<span class="st">"Bill total: $"</span> + <span class="dt">str</span>(bill))
<span class="kw">print</span>(<span class="st">"Tip percentage: "</span> + <span class="dt">str</span>(pct) + <span class="st">"%"</span>)
<span class="kw">print</span>(<span class="st">"Tip amount due: $"</span> + <span class="dt">str</span>(total))
myBill = <span class="dv">100</span>
calculate_tip(myBill, <span class="dv">15</span>)
calculate_tip(myBill, <span class="dv">18</span>)
calculate_tip(myBill, <span class="dv">20</span>)</code></pre></td></tr></table>
<aside id="coding-style">
<p><strong>Coding Style</strong></p>
<p>Now that you are about to write longer, more complex pieces of Python, it is a good time to talk about coding style. Most languages can be written (or more concise, formatted) in different styles; some are more readable than others. Making it easy for others to read your code is always a good idea, and adopting a nice coding style helps tremendously for that.</p>
<p>For Python, <a href="http://www.python.org/dev/peps/pep-0008/">PEP 8 has emerged as the style guide</a> that most projects adhere to; it promotes a very readable and eye-pleasing coding style. Every Python developer should read it at some point; here are the most important points extracted for you:</p>
<ul>
<li>Use 4-space indentation, and no tabs.</li>
<li>4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.</li>
<li>Wrap lines so that they don’t exceed 79 characters.</li>
<li>This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.</li>
<li>Use blank lines to separate functions and classes, and larger blocks of code inside functions.</li>
<li>When possible, put comments on a line of their own.</li>
<li>Use docstrings.</li>
<li>Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) + g(3, 4).</li>
<li>Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods. Always use self as the name for the first method argument (see A First Look at Classes for more on classes and methods).</li>
<li>Don’t use fancy encodings if your code is meant to be used in international environments. Python’s default, UTF-8, or even plain ASCII work best in any case.</li>
<li>Likewise, don’t use non-ASCII characters in identifiers if there is only the slightest chance people speaking a different language will read or maintain the code.</li>
</ul>
</aside>
</section>
<section class="level2" id="composition-functions-can-call-other-functions">
<h2><a href="#composition-functions-can-call-other-functions"><span class="header-section-number">5.2</span> Composition: Functions can call other functions</a></h2>
<p>So far, we have looked at the elements of a program—<code>variables</code>, <code>expressions</code>, and <code>statements</code>—in isolation, without talking about how to combine them.</p>
<p>One of the most useful features of programming languages is their ability to take small building blocks and <strong>compose</strong> them. In our calculate_tip example, we call several Python built-in functions: <code>round</code> to keep our amounts to 2 decimal places and <code>str</code> to convert numeric data (ints and floats) to strings when we print them. As we will see, we can compose our programs of many functions that we define ourselves.</p>
<p>There are some points worth noting here:</p>
<ul>
<li>Functions can call other functions.</li>
<li>A caller of this function might say <code>calculate_tip(myBill, 15)</code>. The parameters of this function, <code>bill</code> and <code>tip</code>, are assigned the values of the myBill variable, and the int literal 15, respectively.</li>
<li>In the body of the function they are just like any other variable.</li>
</ul>
<p>So far, it may not be clear why it is worth the trouble to create all of these new functions. Actually, there are a lot of reasons, but this example demonstrates two:</p>
<ol type="1">
<li>Creating a new function gives us an opportunity to name a group of statements. Functions can simplify a program by hiding a complex computation behind a single command. The function (including its name) can capture our mental chunking, or <em>abstraction</em>, of the problem.<br /></li>
<li>Creating a new function can make a program smaller by eliminating repetitive code.</li>
</ol>
<p>As we might expect, we have to create a function before we can execute it. In other words, the function definition has to be executed before the function is called.</p>
</section>
<section class="level2" id="flow-of-execution">
<h2><a href="#flow-of-execution"><span class="header-section-number">5.3</span> Flow of execution</a></h2>
<p>In order to ensure that a function is defined before its first use, we have to know the order in which statements are executed, which is called the <strong>flow of execution</strong>.</p>
<p>Execution always begins at the first statement of the program. Statements are executed one at a time, in order from top to bottom.</p>
<p>Function definitions do not alter the flow of execution of the program, but remember that statements inside the function are not executed until the function is called. Although it is not common, we can define one function inside another. In this case, the inner definition isn’t executed until the outer function is called.</p>
<p>Function calls are like a detour in the flow of execution. Instead of going to the next statement, the flow jumps to the first line of the called function, executes all the statements there, and then comes back to pick up where it left off.</p>
<p>That sounds simple enough, until we remember that one function can call another. While in the middle of one function, the program might have to execute the statements in another function. But while executing that new function, the program might have to execute yet another function!</p>
<p>Fortunately, Python is adept at keeping track of where it is, so each time a function completes, the program picks up where it left off in the function that called it. When it gets to the end of the program, it terminates.</p>
<p>What’s the moral of this sordid tale? When we read a program, don’t read from top to bottom. Instead, follow the flow of execution.</p>
</section>
<section class="level2" id="functions-that-require-arguments">
<h2><a href="#functions-that-require-arguments"><span class="header-section-number">5.4</span> Functions that require arguments</a></h2>
<p>Most functions require arguments: the arguments provide for generalization. For example, if we want to find the absolute value of a number, we have to indicate what the number is. Python has a built-in function for computing the absolute value:</p>
<pre class="sourceCode python"><code class="sourceCode python">>>> <span class="dt">abs</span>(<span class="dv">5</span>)
<span class="dv">5</span>
>>> <span class="dt">abs</span>(-<span class="dv">5</span>)
<span class="dv">5</span></code></pre>
<p>In this example, the arguments to the <code>abs</code> function are 5 and -5.</p>
<p>Some functions take more than one argument. For example the built-in function <code>round</code> takes two arguments, the number to round and the (optional) number of decimal digits of precision. Inside the function, the values that are passed get assigned to variables called <strong>parameters</strong>.</p>
<pre class="sourceCode python"><code class="sourceCode python">>>> <span class="dt">round</span>(<span class="fl">3.14159</span>)
<span class="dv">3</span>
>>> <span class="dt">round</span>(<span class="fl">3.14159</span>,<span class="dv">3</span>)
<span class="fl">3.142</span></code></pre>
<p>Another built-in function that takes more than one argument is <code>max</code>.</p>
<pre class="sourceCode python"><code class="sourceCode python">>>> <span class="dt">max</span>(<span class="dv">7</span>, <span class="dv">11</span>)
<span class="dv">11</span>
>>> <span class="dt">max</span>(<span class="dv">4</span>, <span class="dv">1</span>, <span class="dv">17</span>, <span class="dv">2</span>, <span class="dv">12</span>)
<span class="dv">17</span>
>>> <span class="dt">max</span>(<span class="dv">3</span> * <span class="dv">11</span>, <span class="dv">5</span>**<span class="dv">3</span>, <span class="dv">512</span> - <span class="dv">9</span>, <span class="dv">1024</span>**<span class="dv">0</span>)
<span class="dv">503</span></code></pre>
<p><code>max</code> can be passed any number of arguments, separated by commas, and will return the largest value passed. The arguments can be either simple values or expressions. In the last example, 503 is returned, since it is larger than 33, 125, and 1.</p>
</section>
<section class="level2" id="functions-that-return-values">
<h2><a href="#functions-that-return-values"><span class="header-section-number">5.5</span> Functions that return values</a></h2>
<p>All the functions in the previous section return values. Furthermore, functions like <code>range</code>, <code>int</code>, <code>abs</code> all return values that can be used to build more complex expressions.</p>
<p>So an important difference between these functions and one like <code>calculate_tip</code> is that <code>calculate_tip</code> does not return a useful value — it computes a value and displays the results on the screen.</p>
<p>A function that returns a value is called a <strong>fruitful function</strong> in this book. The opposite of a fruitful function is <strong>void function</strong> — one that is not executed for its resulting value, but is executed because it does something useful. (Languages like Java, C#, C and C++ use the term “void function”, other languages like Pascal call it a <strong>procedure</strong>.) Even though void functions are not executed for their resulting value, Python always wants to return something. So if the programmer doesn’t arrange to return a value, Python will automatically return the value <code>None</code>.</p>
<p>How do we write our own fruitful function? Let’s look at the standard formula for compound interest as an example fo a fruitful function:</p>
<figure>
<img src="figs/compoundInterest.png" />
</figure>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> final_amt(p, r, n, t):
<span class="co">"""</span>
<span class="co"> Apply the compound interest formula to p</span>
<span class="co"> to produce the final amount.</span>
<span class="co"> """</span>
a = p * (<span class="dv">1</span> + r/n) ** (n*t)
<span class="kw">return</span> a <span class="co"># This is new, and makes the function fruitful.</span>
<span class="co"># now that we have the function above, let us call it. </span>
toInvest = <span class="dt">float</span>(<span class="dt">input</span>(<span class="st">"How much do you want to invest?"</span>))
fnl = final_amt(toInvest, <span class="fl">0.08</span>, <span class="dv">12</span>, <span class="dv">5</span>)
<span class="kw">print</span>(<span class="st">"At the end of the period you'll have"</span>, fnl)</code></pre></td></tr></table>
<ul>
<li>The <strong>return</strong> statement is followed an expression (<code>a</code> in this case). This expression will be evaluated and returned to the caller as the “fruit” of calling this function.</li>
<li>We prompted the user for the principal amount. The type of <code>toInvest</code> is a string, but we need a number before we can work with it. Because it is money, and could have decimal places, we’ve used the <code>float</code> type converter function to parse the string and return a float.</li>
<li>Notice how we entered the arguments for 8% interest, compounded 12 times per year, for 5 years.</li>
<li><p>When we run this, we get the output</p>
<p><em>At the end of the period you’ll have 14898.457083</em></p></li>
</ul>
<p>This is a bit messy with all these decimal places, but remember that Python doesn’t understand that we’re working with money: it just does the calculation to the best of its ability, without rounding. Later we’ll see how to format the string that is printed in such a way that it does get nicely rounded to two decimal places before printing. * The line <code>toInvest = float(input("How much do you want to invest?"))</code> also shows yet another example of <em>composition</em> — we can call a function like <code>float</code>, and its arguments can be the results of other function calls (like <code>input</code>) that we’ve called along the way.</p>
<p>Notice something else very important here. The name of the variable we pass as an argument — <code>toInvest</code> — has nothing to do with the name of the parameter — <code>p</code>. It is as if <code>p = toInvest</code> is executed when <code>final_amt</code> is called. It doesn’t matter what the value was named in the caller, in <code>final_amt</code> its name is <code>p</code>.</p>
<p>These short variable names are getting quite tricky, so perhaps we’d prefer one of these versions instead:</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> final_amt_v2(principalAmount, nominalPercentageRate,
numTimesPerYear, years):
a = principalAmount * (<span class="dv">1</span> + nominalPercentageRate /
numTimesPerYear) ** (numTimesPerYear*years)
<span class="kw">return</span> a
<span class="kw">def</span> final_amt_v3(amt, rate, compounded, years):
a = amt * (<span class="dv">1</span> + rate/compounded) ** (componded*years)
<span class="kw">return</span> a</code></pre></td></tr></table>
<p>They all do the same thing. Use your judgement to write code that can be best understood by other humans!<br />Short variable names are more economical and sometimes make code easier to read: E = mc<sup>2</sup> would not be nearly so memorable if Einstein had used longer variable names! If you do prefer short names, make sure you also have some comments to enlighten the reader about what the variables are used for.</p>
<hr />
<p>When we create a <strong>local variable</strong> inside a function, it only exists inside the function, and we cannot use it outside. For example, consider again this function:</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> final_amt(p, r, n, t):
a = p * (<span class="dv">1</span> + r/n) ** (n*t)
<span class="kw">return</span> a </code></pre></td></tr></table>
<p>If we try to use <code>a</code>, outside the function, we’ll get an error:</p>
<pre class="sourceCode python"><code class="sourceCode python">>>> a
<span class="ot">NameError</span>: name <span class="st">'a'</span> is not defined</code></pre>
<p>The variable <code>a</code> is local to <code>final_amt</code>, and is not visible outside the function.</p>
<p>Additionally, <code>a</code> only exists while the function is being executed — we call this its <strong>lifetime</strong>. When the execution of the function terminates, the local variables are destroyed.</p>
<p>Parameters are also local, and act like local variables. For example, the lifetimes of <code>p</code>, <code>r</code>, <code>n</code>, <code>t</code> begin when <code>final_amt</code> is called, and the lifetime ends when the function completes its execution.</p>
<p>So it is not possible for a function to set some local variable to a value, complete its execution, and then when it is called again next time, recover the local variable. Each call of the function creates new local variables, and their lifetimes expire when the function returns to the caller.</p>
</section>
<section class="level2" id="tips-revisited">
<h2><a href="#tips-revisited"><span class="header-section-number">5.6</span> Tips Revisited</a></h2>
<p>Now that we have fruitful functions, we can focus our attention on reorganizing our code so that it fits more nicely into our mental chunks.<br />This process of rearrangement is called <strong>refactoring</strong> the code.</p>
<p>Two things want to do in our tip calculator is to find the amount of the tip and show the results to the user. In the example below, we separate the various functions of the program to make a more complete tip calculator. As you’ll see, we’re starting to build code that is useful. Using functions allows us to make changes to one part of a program without affecting other parts of the program. For example, we can change the welcome message without worrying about breaking our calculations.</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> welcome():
<span class="co">"""</span>
<span class="co"> Give the user a welcome message.</span>
<span class="co"> """</span>
<span class="kw">print</span>(<span class="st">"""</span>
<span class="st">-----------------------------------</span>
<span class="st"> Welcome to the Tip Calculator </span>
<span class="st">-----------------------------------</span>
<span class="st">"""</span>)
<span class="kw">def</span> calc_tip(bill, pct):
<span class="co">"""</span>
<span class="co"> Calculate the tip on a bill, given the pct of the tip.</span>
<span class="co"> Return the amount of the tip</span>
<span class="co"> """</span>
tip = bill * (pct * .<span class="dv">01</span>) <span class="co"># convert pct to a decimal and calculate</span>
tip = <span class="dt">round</span>(tip, <span class="dv">2</span>) <span class="co"># round the tip to 2 decimal places</span>
<span class="kw">return</span> tip
<span class="kw">def</span> get_bill_amt():
<span class="co">"""</span>
<span class="co"> Ask the user to enter the amount of the bill</span>
<span class="co"> and return this amount as a <float></span>
<span class="co"> """</span>
<span class="kw">return</span> <span class="dt">float</span>(<span class="dt">input</span>(<span class="st">"How much was your total bill: "</span>))
<span class="kw">def</span> get_tip_pct():
<span class="co">"""</span>
<span class="co"> Allow the user to choose a tip amount</span>
<span class="co"> from a menu.</span>
<span class="co"> """</span>
<span class="kw">print</span>(<span class="st">"""</span>
<span class="st">What percent tip do you want to leave?</span>
<span class="st"> 1 - 10%, lousy service</span>
<span class="st"> 2 - 15%, good service, but I'm cheap</span>
<span class="st"> 3 - 20%, the server is hard working and deserves a decent tip</span>
<span class="st"> 4 - 25%, outstanding service"""</span>)
menu = <span class="dt">input</span>(<span class="st">"enter your choice (1-4):"</span>)
<span class="kw">if</span> menu == <span class="st">"1"</span>:
<span class="kw">return</span> <span class="dv">10</span>
<span class="kw">if</span> menu == <span class="st">"2"</span>:
<span class="kw">return</span> <span class="dv">15</span>
<span class="kw">if</span> menu == <span class="st">"3"</span>:
<span class="kw">return</span> <span class="dv">20</span>
<span class="kw">if</span> menu == <span class="st">"4"</span>:
<span class="kw">return</span> <span class="dv">25</span>
<span class="kw">return</span> -<span class="dv">1</span> <span class="co"># return -1 for any invalid choice</span>
<span class="kw">def</span> show_results(bill, tip, pct):
<span class="co">"""</span>
<span class="co"> Prints a message to the user showing</span>
<span class="co"> the result of the calculations.</span>
<span class="co"> """</span>
total = tip + bill
<span class="kw">print</span>(<span class="st">"Bill amount: $"</span> + <span class="dt">str</span>(bill))
<span class="kw">print</span>(<span class="st">"Tip percentage: "</span> + <span class="dt">str</span>(pct) + <span class="st">"%"</span>)
<span class="kw">print</span>(<span class="st">"Tip amount due: $"</span> + <span class="dt">str</span>(total))
<span class="kw">print</span>(<span class="st">"""</span>
<span class="st">-----------------------------------</span>
<span class="st"> GOOD BYE </span>
<span class="st">-----------------------------------</span>
<span class="st">"""</span>)
<span class="kw">def</span> main():
<span class="co">"""</span>
<span class="co"> Read in the basic information, calcualte the tip</span>
<span class="co"> and the share, then dispaly the results to the user.</span>
<span class="co"> """</span>
welcome()
myBill = get_bill_amt()
pct = get_tip_pct()
tip = calc_tip(myBill, pct)
show_results(myBill, tip, pct)
<span class="kw">if</span> <span class="dt">__name__</span> == <span class="st">"__main__"</span>:
main()</code></pre></td></tr></table>
<p><a href="examples/tip2.py">Download and run the source code: tip2.py</a></p>
<p>The trick about refactoring code is to anticipate which things we are likely to want to change each time we call the function: these should become the parameters, or changeable parts, of the functions we write.</p>
<aside id="main">
<p><strong>The <code>main</code> function</strong></p>
<p>In our code example above, we encounter Python’s special syntax for running a program from the command line:</p>
<pre class="sourceCode python"><code class="sourceCode python"><span class="kw">if</span> <span class="dt">__name__</span> == <span class="st">"__main__"</span>:
main()</code></pre>
<p>This conditional statement allows the program to execute code if it is being run as a standalone Python program. In our case, we choose to call the <code>main</code> function which we defined. main() has no special meaning in Python, though, and we could execute any statements we choose under that block.</p>
</aside>
</section>
<section class="level2" id="glossary">
<h2><a href="#glossary"><span class="header-section-number">5.7</span> Glossary</a></h2>
<dl>
<dt>argument</dt>
<dd><p>A value provided to a function when the function is called. This value is assigned to the corresponding parameter in the function. The argument can be the result of an expression which may involve operators, operands and calls to other fruitful functions.</p>
</dd>
<dt>body</dt>
<dd><p>The second part of a compound statement. The body consists of a sequence of statements all indented the same amount from the beginning of the header. The standard amount of indentation used within the Python community is 4 spaces.</p>
</dd>
<dt>compound statement</dt>
<dd><p>A statement that consists of two parts:</p>
<ol type="1">
<li>header - which begins with a keyword determining the statement type, and ends with a colon.</li>
<li>body - containing one or more statements indented the same amount from the header.</li>
</ol>
<p>The syntax of a compound statement looks like this:</p>
<pre class="sourceCode python"><code class="sourceCode python">keyword ... :
statement
statement ...</code></pre>
</dd>
<dt>docstring</dt>
<dd><p>A special string that is attached to a function as its <code>__doc__</code> attribute. Tools like PyScripter can use docstrings to provide documentation or hints for the programmer. When we get to modules, classes, and methods, we’ll see that docstrings can also be used there.</p>
</dd>
<dt>flow of execution</dt>
<dd><p>The order in which statements are executed during a program run.</p>
</dd>
<dt>frame</dt>
<dd><p>A box in a stack diagram that represents a function call. It contains the local variables and parameters of the function.</p>
</dd>
<dt>function</dt>
<dd><p>A named sequence of statements that performs some useful operation. Functions may or may not take parameters and may or may not produce a result.</p>
</dd>
<dt>function call</dt>
<dd><p>A statement that executes a function. It consists of the name of the function followed by a list of arguments enclosed in parentheses.</p>
</dd>
<dt>function composition</dt>
<dd><p>Using the output from one function call as the input to another.</p>
</dd>
<dt>function definition</dt>
<dd><p>A statement that creates a new function, specifying its name, parameters, and the statements it executes.</p>
</dd>
<dt>fruitful function</dt>
<dd><p>A function that returns a value when it is called.</p>
</dd>
<dt>header line</dt>
<dd><p>The first part of a compound statement. A header line begins with a keyword and ends with a colon (:)</p>
</dd>
<dt>import statement</dt>
<dd><p>A statement which permits functions and variables defined in another Python module to be brought into the environment of another script. To use the features of the turtle, we need to first import the turtle module.</p>
</dd>
<dt>lifetime</dt>
<dd><p>Variables and objects have lifetimes — they are created at some point during program execution, and will be destroyed at some time.</p>
</dd>
<dt>local variable</dt>
<dd><p>A variable defined inside a function. A local variable can only be used inside its function. Parameters of a function are also a special kind of local variable.</p>
</dd>
<dt>parameter</dt>
<dd><p>A name used inside a function to refer to the value which was passed to it as an argument.</p>
</dd>
<dt>refactor</dt>
<dd><p>A fancy word to describe reorganizing our program code, usually to make it more understandable. Typically, we have a program that is already working, then we go back to “tidy it up”. It often involves choosing better variable names, or spotting repeated patterns and moving that code into a function.</p>
</dd>
<dt>stack diagram</dt>
<dd><p>A graphical representation of a stack of functions, their variables, and the values to which they refer.</p>
</dd>
<dt>traceback</dt>
<dd><p>A list of the functions that are executing, printed when a runtime error occurs. A traceback is also commonly refered to as a <em>stack trace</em>, since it lists the functions in the order in which they are stored in the <code>runtime stack <http://en.wikipedia.org/wiki/Runtime_stack></code>__.</p>
</dd>
<dt>void function</dt>
<dd><p>The opposite of a fruitful function: one that does not return a value. It is executed for the work it does, rather than for the value it returns.</p>
</dd>
</dl>
</section>
<section class="level2" id="exercises">
<h2><a href="#exercises"><span class="header-section-number">5.8</span> Exercises</a></h2>
<ol type="1">
<li><p>Write a void (non-fruitful) function to that prints out centered text to the console. Your function should have two parameters, <code>text</code>—the string to center, and <code>maxLen</code>—the width of the document (in spaces).<br /> (Hint: you will want to use the built-in <code>len</code> function and might want to use the * operator with spaces.)</p></li>
<li><p>Write a function <code>area_of_circle(r)</code> which returns the area of a circle of radius <code>r</code>.<br /> (Hint: if you can’t remember how to find the area of a circle, look it up or ask a friend.)</p></li>
<li><p><em>Lemonade Stand</em>. Diego has a lemonade stand and he needs a program to estimate costs. Write a Python program called lemonade.py that allows him to see potential profits for his stand. Use the following skeleton to start your program:</p>
<table class="sourceCode python numberLines"><tr class="sourceCode"><td class="lineNumbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="sourceCode"><pre><code class="sourceCode python"><span class="kw">def</span> estimate_profit(lemonCost, cupCost, estPeople, price):
<span class="co"># write a doc string</span>
<span class="co"># write the code</span>
<span class="co"># return the estimate</span>
<span class="kw">def</span> main():
l = .<span class="dv">3</span>
c = .<span class="dv">15</span>
n = <span class="dv">100</span>
p = <span class="fl">2.50</span>
profit = estimate_profit(l, c, n, p)
show_results(l, c, n, p, price) <span class="co"># you need to define this one yourself</span>
<span class="kw">if</span> <span class="dt">__name__</span> == <span class="st">"__main__"</span>:
main()</code></pre></td></tr></table></li>
</ol>
</section>
</section>
<section class="level1" id="contributor-list">
<h1><a href="#contributor-list"><span class="header-section-number">6</span> Contributor List</a></h1>
<p>To paraphrase the philosophy of the Free Software Foundation, this book is free like free speech, but not necessarily free like free pizza. It came about because of a collaboration that would not have been possible without the GNU Free Documentation License. So we would like to thank the Free Software Foundation for developing this license and, of course, making it available to us.</p>
<p>We would also like to thank the more than 100 sharp-eyed and thoughtful readers who have sent us suggestions and corrections over the past few years. In the spirit of free software, we decided to express our gratitude in the form of a contributor list. Unfortunately, this list is not complete, but we are doing our best to keep it up to date. It was also getting too large to include everyone who sends in a typo or two. You have our gratitude, and you have the personal satisfaction of making a book you found useful better for you and everyone else who uses it. New additions to the list for the 2nd edition will be those who have made on-going contributions.</p>
<p>If you have a chance to look through the list, you should realize that each person here has spared you and all subsequent readers from the confusion of a technical error or a less-than-transparent explanation, just by sending us a note.</p>
<p>Impossible as it may seem after so many corrections, there may still be errors in this book. If you should stumble across one, we hope you will take a minute to contact us. The email address (for the Python 3 version of the book) is <code>p.wentworth@ru.ac.za <mailto:p.wentworth@ru.ac.za></code>__ . Substantial changes made due to your suggestions will add you to the next version of the contributor list (unless you ask to be omitted). Thank you!</p>
<section class="level2" id="second-edition">
<h2><a href="#second-edition"><span class="header-section-number">6.1</span> Second Edition</a></h2>
<ul>
<li>An email from Mike MacHenry set me straight on tail recursion. He not only pointed out an error in the presentation, but suggested how to correct it.</li>
<li>It wasn’t until 5th Grade student Owen Davies came to me in a Saturday morning Python enrichment class and said he wanted to write the card game, Gin Rummy, in Python that I finally knew what I wanted to use as the case study for the object oriented programming chapters.</li>
<li>A <em>special</em> thanks to pioneering students in Jeff’s Python Programming class at <code>GCTAA <http://www.arlington.k12.va.us/1540108115320583/blank/browse.asp?A=383&BMDRN=2000&BCOB=0&C=59085></code>__ during the 2009-2010 school year: Safath Ahmed, Howard Batiste, Louis Elkner-Alfaro, and Rachel Hancock. Your continual and thoughtfull feedback led to changes in most of the chapters of the book. You set the standard for the active and engaged learners that will help make the new Governor’s Academy what it is to become. Thanks to you this is truly a <em>student tested</em> text.</li>
<li>Thanks in a similar vein to the students in Jeff’s Computer Science class at the HB-Woodlawn program during the 2007-2008 school year: James Crowley, Joshua Eddy, Eric Larson, Brian McGrail, and Iliana Vazuka.</li>
<li>Ammar Nabulsi sent in numerous corrections from Chapters 1 and 2.</li>
<li>Aldric Giacomoni pointed out an error in our definition of the Fibonacci sequence in Chapter 5.</li>
<li>Roger Sperberg sent in several spelling corrections and pointed out a twisted piece of logic in Chapter 3.</li>
<li>Adele Goldberg sat down with Jeff at PyCon 2007 and gave him a list of suggestions and corrections from throughout the book.</li>
<li>Ben Bruno sent in corrections for chapters 4, 5, 6, and 7.</li>
<li>Carl LaCombe pointed out that we incorrectly used the term commutative in chapter 6 where symmetric was the correct term.</li>
<li>Alessandro Montanile sent in corrections for errors in the code examples and text in chapters 3, 12, 15, 17, 18, 19, and 20.</li>
<li>Emanuele Rusconi found errors in chapters 4, 8, and 15.</li>
<li>Michael Vogt reported an indentation error in an example in chapter 6, and sent in a suggestion for improving the clarity of the shell vs. script section in chapter 1.</li>
</ul>
</section>
<section class="level2" id="first-edition">
<h2><a href="#first-edition"><span class="header-section-number">6.2</span> First Edition</a></h2>
<ul>
<li>Lloyd Hugh Allen sent in a correction to Section 8.4.</li>
<li>Yvon Boulianne sent in a correction of a semantic error in Chapter 5.</li>
<li>Fred Bremmer submitted a correction in Section 2.1.</li>
<li>Jonah Cohen wrote the Perl scripts to convert the LaTeX source for this book into beautiful HTML.</li>
<li>Michael Conlon sent in a grammar correction in Chapter 2 and an improvement in style in Chapter 1, and he initiated discussion on the technical aspects of interpreters.</li>
<li>Benoit Girard sent in a correction to a humorous mistake in Section 5.6.</li>
<li>Courtney Gleason and Katherine Smith wrote <code>horsebet.py</code>, which was used as a case study in an earlier version of the book. Their program can now be found on the website.</li>
<li>Lee Harr submitted more corrections than we have room to list here, and indeed he should be listed as one of the principal editors of the text.</li>
<li>James Kaylin is a student using the text. He has submitted numerous corrections.</li>
<li>David Kershaw fixed the broken <code>catTwice</code> function in Section 3.10.</li>
<li>Eddie Lam has sent in numerous corrections to Chapters 1, 2, and 3. He also fixed the Makefile so that it creates an index the first time it is run and helped us set up a versioning scheme.</li>
<li>Man-Yong Lee sent in a correction to the example code in Section 2.4.</li>
<li>David Mayo pointed out that the word unconsciously in Chapter 1 needed to be changed to subconsciously .</li>
<li>Chris McAloon sent in several corrections to Sections 3.9 and 3.10.</li>
<li>Matthew J. Moelter has been a long-time contributor who sent in numerous corrections and suggestions to the book.</li>
<li>Simon Dicon Montford reported a missing function definition and several typos in Chapter 3. He also found errors in the <code>increment</code> function in Chapter 13.</li>
<li>John Ouzts corrected the definition of return value in Chapter 3.</li>
<li>Kevin Parks sent in valuable comments and suggestions as to how to improve the distribution of the book.</li>
<li>David Pool sent in a typo in the glossary of Chapter 1, as well as kind words of encouragement.</li>
<li>Michael Schmitt sent in a correction to the chapter on files and exceptions.</li>
<li>Robin Shaw pointed out an error in Section 13.1, where the printTime function was used in an example without being defined.</li>
<li>Paul Sleigh found an error in Chapter 7 and a bug in Jonah Cohen’s Perl script that generates HTML from LaTeX.</li>
<li>Craig T. Snydal is testing the text in a course at Drew University. He has contributed several valuable suggestions and corrections.</li>
<li>Ian Thomas and his students are using the text in a programming course. They are the first ones to test the chapters in the latter half of the book, and they have make numerous corrections and suggestions.</li>
<li>Keith Verheyden sent in a correction in Chapter 3.</li>
<li>Peter Winstanley let us know about a longstanding error in our Latin in Chapter 3.</li>
<li>Chris Wrobel made corrections to the code in the chapter on file I/O and exceptions.</li>
<li>Moshe Zadka has made invaluable contributions to this project. In addition to writing the first draft of the chapter on Dictionaries, he provided continual guidance in the early stages of the book.</li>
<li>Christoph Zwerschke sent several corrections and pedagogic suggestions, and explained the difference between <em>gleich</em> and <em>selbe</em>.</li>
<li>James Mayer sent us a whole slew of spelling and typographical errors, including two in the contributor list.</li>
<li>Hayden McAfee caught a potentially confusing inconsistency between two examples.</li>
<li>Angel Arnal is part of an international team of translators working on the Spanish version of the text. He has also found several errors in the English version.</li>
<li>Tauhidul Hoque and Lex Berezhny created the illustrations in Chapter 1 and improved many of the other illustrations.</li>
<li>Dr. Michele Alzetta caught an error in Chapter 8 and sent some interesting pedagogic comments and suggestions about Fibonacci and Old Maid.</li>
<li>Andy Mitchell caught a typo in Chapter 1 and a broken example in Chapter 2.</li>
<li>Kalin Harvey suggested a clarification in Chapter 7 and caught some typos.</li>
<li>Christopher P. Smith caught several typos and is helping us prepare to update the book for Python 2.2.</li>
<li>David Hutchins caught a typo in the Foreword.</li>
<li>Gregor Lingl is teaching Python at a high school in Vienna, Austria. He is working on a German translation of the book, and he caught a couple of bad errors in Chapter 5.</li>
<li>Julie Peters caught a typo in the Preface.</li>
</ul>
</section>
</section>
</body>
</html>