Books Never Written Math Beginning Your Exercise Program By

Books Never Written Joke for All scouts Cub Scouts Webelos Boy Scouts My Blog. Activities Advancements Awards. 'Over the Mountaintop' by Hugo First 'The Numbers Game' by Cal Q. I tell them to my friends and family all the time. But the funniest part is when I tell them a book never written and they bust out laughing. Books never written math worksheet answers my long life in crime generated on lbartman.com show printable version!!! Hide the show to save images bellow, right click on shown image then save as.png. The 10 Best Self-Help Books You’ve (Probably) Never Heard Of. (deceptively) simple exercise of itemizing your desires in a list. If approached with maturity, Jarrett’s exercise amounts to a personal inventory-taking and a meaningful assessment of one’s true aims. — This pioneering work written by a Swedenborgian. Book publishers,top selling authors,top selling books,best book authors,best short story writers,essay topics,new book titles,source of new books,weird books,best selling books,discount book supply,librarian jobs. “How To Exercise” by Eileen and Ben Dover. Send your “Books Never Written.

Ian Stewart is an Emeritus Professor of Mathematics at Warwick University and a Fellow of the Royal Society. He has written over 80 books, mainly popular mathematics, and has won three gold medals for his work on the public understanding of science. In collaboration with Terry Pratchett and Jack Cohen he wrote the Science of Discworld series. His new book, 17 Equations That Changed the World, is published by Profile.

'Popular mathematics' may sound like a contradiction in terms. That's what makes the genre so important: we have to change that perception. Mathematics is the Cinderella science: undervalued, underestimated, and misunderstood. Yet it has been one of the main driving forces behind human society for at least three millennia, it powers all of today's technology, and it underpins almost every aspect of our daily lives.

'It's not really surprising that few outside the subject appreciate it, though. School mathematics is so focused on getting the right answer and passing the exam that there is seldom an opportunity to find out what it's all for. The hard core of real mathematics is extremely difficult, and it takes six or seven years to train a research mathematician after they leave school. Popular mathematics provides an entry route for non-specialists. It allows them to appreciate where mathematics came from, who created it, what it's good for, and where it's going, without getting tangled up in the technicalities. It's like listening to music instead of composing it.

'There are many ways to make real mathematics accessible. Its history reveals the subject as a human activity and gives a feel for the broad flow of ideas over the centuries. Biographies of great mathematicians tell us what it's like to work at the frontiers of human knowledge. The great problems, the ones that hit the news media when they are finally solved after centuries of effort, are always fascinating. So are the unsolved ones and the latest hot research areas. The myriad applications of mathematics, from medicine to the iPad, are an almost inexhaustible source of inspiration.'

1. The Man Who Knew Infinity by Robert Kanigel


The self-taught Indian genius Srinivasa Ramanujan had a flair for strange and beautiful formulas, so unusual that mathematicians are still coming to grips with their true meaning. He was born into a poor Brahmin family in 1887 and was pursuing original research in his teens. In 1912, he was brought to work at Cambridge. He died of malnutrition and other unknown causes in 1920, leaving a rich legacy that is still not fully understood. There has never been another mathematical life story like it: absolutely riveting.

2. Gödel, Escher, Bach by Douglas Hofstadter


One of the great cult books, a very original take on the logical paradoxes associated with self-reference, such as 'this statement is false'. Hofstadter combines the mathematical logic of Kurt Gödel, who proved that some questions in arithmetic can never be answered, with the etchings of Maurits Escher and the music of Bach. Frequent dramatic dialogues between Lewis Carroll's characters Achilles and the Tortoise motivate key topics in a highly original manner, along with their friend Crab who invents the tortoise-chomping record player. DNA and computers get extensive treatment too.

3. The Colossal Book of Mathematics by Martin Gardner


In his long-running Mathematical Games column in Scientific American, Gardner – a journalist with no mathematical training – created the field of recreational mathematics. On the surface his columns were about puzzles and games, but they all concealed mathematical principles, some simple, some surprisingly deep. He combined a playful and clear approach to his subject with a well-developed taste for what was mathematically significant. The book consists of numerous selections from his columns, classified according to the mathematical area involved. Learn how to make a hexaflexagon and why playing Brussels sprouts is a waste of time.

4. Euclid in the Rainforest by Joseph Mazur


A thoroughly readable account of the meaning of truth in mathematics, presented through a series of quirky adventures in the Greek Islands, the jungles around the Orinoco River, and elsewhere. Examines tricky concepts like infinity, topology, and probability through tall tales and anecdotes. Three different kinds of truth are examined: formal classical logic, the role of the infinite, and inference by plausible reasoning. The story of the student who believed nothing except his calculator is an object lesson for everyone who thinks mathematics is just 'sums'.

5. Four Colours Suffice by Robin Wilson


In 1852 Francis Guthrie, a young South African mathematician, was attempting to colour the counties in a map of England. Guthrie discovered that he needed only four different colours to ensure that any two adjacent counties had different colours. After some experimentation he convinced himself that the same goes for any map whatsoever. This is the remarkable story of how mathematicians eventually proved he was right, but only with the aid of computers, bringing into question the meaning of 'proof'. It contains enough detail to be satisfying, but remains accessible and informative throughout.

6. What is Mathematics Really? by Reuben Hersh


The classic text What is Mathematics? by Richard Courant and Herbert Robbins focused on the subject's nuts and bolts. It answered its title question by example. Hersh takes a more philosophical view, based on his experience as a professional mathematician. The common working philosophy of most mathematicians is a kind of vague Platonism: mathematical concepts have some sort of independent existence in some ideal world. Although this is what it feels like to insiders, Hersh argues that mathematics is a collective human construct – like money or the Supreme Court. However, it is a construct constrained by its own internal logic; it's not arbitrary. You choose the concepts that interest you, but you don't get to choose how they behave.

7. Magical Mathematics by Persi Diaconis and Ron Graham


Both authors are top-rank mathematicians with years of stage performances behind them, and their speciality is mathematical magic. They show how mathematics relates to juggling and reveal the secrets behind some amazing card tricks. Here's one. The magician mails a pack of cards to anyone, asking them to shuffle it and choose a card. Then he shuffles the cards again, and mails half of them to the magician—not saying whether the chosen card is included. By return mail, the magician names the selected card. No trickery: it all depends on the mathematics of shuffles.

8. Games of Life by Karl Sigmund


Biologists' understanding of many vital features of the living world, such as sex and survival, depends on the theory of evolution. One of the basic theoretical tools here is the mathematics of game theory, in which several players compete by choosing from a list of possible strategies. The children's game of rock-paper-scissors is a good example. The book illuminates such questions as how genes spread through a population and the evolution of cooperation, by finding the best strategies for games such as cat and mouse, the battle of the sexes, and the prisoner's dilemma. On the borderline between popular science and an academic text, but eminently readable without specialist knowledge.

9. Mathenauts: Tales of Mathematical Wonder edited by Rudy Rucker


A collection of 23 science fiction short stories, each of which centres on mathematics. Two are by Martin Gardner, and many of the great writers of SF are represented: Isaac Asimov, Gregory Benford, Larry Niven, Frederik Pohl. The high point is Norman Kagan's utterly hilarious 'The Mathenauts', in which only mathematicians can travel through space, because space is mathematical – and, conversely, anything mathematical can be reality. An isomorphomechanism is essential equipment. Between them, these tales cover most of the undergraduate mathematics syllabus, though not in examinable form.

10. The Mathematical Principles of Natural Philosophy by Isaac Newton


There ought to be a great classic in this top 10, and there is none greater. I've put it last because it's not popularisation in the strict sense. However, it slips in because it communicated to the world one of the very greatest ideas of all time: Nature has laws, and they can be expressed in the language of mathematics. Using nothing more complicated than Euclid's geometry, Newton developed his laws of motion and gravity, applying them to the motion of the planets and strange wobbles in the position of the Moon. He famously said that he 'stood on the shoulders of giants', and so he did, but this book set the scientific world alight. As John Maynard Keyes wrote, Newton was a transitional figure of immense stature: 'the last of the magicians … the last wonderchild to whom the Magi could do sincere and appropriate homage.' No mathematical book has had more impact.

< Think Python
The latest reviewed version was checked on 4 November 2016. There are template/file changes awaiting review.
  • 1Preface
    • 1.1Chapter 0: Preface
  • 2The way of the program
    • 2.3What is debugging?
    • 2.8Exercises
  • 3Variables, expressions and statements
    • 3.2Variables
    • 3.6Expressions
    • 3.12Exercises
  • 4Functions
    • 4.6Definitions and uses
    • 4.15Exercises
  • 5Case study: interface design
  • 6Conditional and recursion
  • 7Fruitful functions
    • 7.1Return values
    • 7.2Incremental development
    • 7.11Exercises
  • 8Iteration
    • 8.9Exercises
  • 9Strings
    • 9.3Traversal with a for loop
    • 9.4String slices
    • 9.6Searching
    • 9.13Exercises
  • 10Case study: word play
    • 10.7Exercises
  • 11Lists
    • 11.7Map, filter and reduce
    • 11.12List arguments
    • 11.15Exercises
  • 12Dictionaries
    • 12.2Dictionary as a set of counters
    • 12.3Looping and dictionaries
    • 12.5Dictionaries and lists
    • 12.6Memos
    • 12.8Long integers
    • 12.11Exercise-8
  • 13Tuples
    • 13.4Variable-length argument tuples
    • 13.7Comparing tuples
    • 13.11Exercises
    • 13.12Word frequency analysis
    • 13.13Random numbers
    • 13.17Dictionary subtraction
    • 13.18Random words
    • 13.19Markov analysis
    • 13.23Exercises
  • 14Files
    • 14.4Filenames and paths
  • 15Classes and objects
    • 15.2Attributes
    • 15.5Objects are mutable
    • 15.6Copying
    • 15.9Exercises
  • 16Classes and functions
    • 16.1Time
    • 16.7Exercises
  • 17Classes and methods
    • 17.2Printing objects
    • 17.5The init method
    • 17.6The __str__ method
    • 17.7Operator overloading
    • 17.8Type-based dispatch
    • 17.12Exercises
  • 18Inheritance
    • 18.3Comparing cards
    • 18.6Add, remove, shuffle and sort
    • 18.8Class diagrams
    • 18.11Exercises
  • 19Debugging
    • 19.1Syntax errors
    • 19.2Runtime errors
      • 19.2.2My program hangs
    • 19.3Semantic errors
  • 20Answers
    • 20.1Chapter 1
    • 20.2Chapter 2
    • 20.3Chapter 3
    • 20.4Chapter 4
    • 20.5Chapter 5
    • 20.6Chapter 9
    • 20.7Chapter 10
    • 20.8Chapter 11
    • 20.9Chapter 12
    • 20.10Chapter 13
    • 20.11Chapter 14
    • 20.12Chapter 15
    • 20.13Chapter 16
    • 20.14Chapter 17
    • 20.15Chapter 3.5
    • 20.16Appendix B
  • 21Index

Chapter 0: Preface[edit]

The strange history of this book[edit]

(This section was written by Allen B. Downey[1])

In January 1999, I was preparing to teach an introductory programming class in Java. I had taught it three times and I was getting frustrated. The failure rate in the class was too high and, even for students who succeeded, the overall level of achievement was too low.

One of the problems I saw was the books. They were too big, with too much unnecessary detail about Java, and not enough high-level guidance about how to program. And they all suffered from the 'trapdoor effect': they would start out easy, proceed gradually, and then somewhere around Chapter 5 the bottom would fall out. The students would get too much new material, too fast, and I would spend the rest of the semester picking up the pieces.

Two weeks before the first day of class, I decided to write my own book.

My goals were:

  • Keep it short. It is better for students to read 10 pages than read 50 pages.
  • Be careful with vocabulary. I tried to minimize the jargon and define each term at first use.
  • Build gradually. To avoid trapdoors, I took the most difficult topics and split them into a series of small steps.
  • Focus on programming, not the programming language. I included the minimum useful subset of Java and left out the rest.

I needed a title, so on a whim I chose How to Think Like a Computer Scientist.

My first version was rough, but it worked. Students did the reading, and they understood enough that I could spend class time on the hard topics, the interesting topics and (most important) letting the students practice.

I released the book under the GNU Free Documentation License, which allows users to copy, modify, and distribute the book.

What happened next is the cool part. Jeff Elkner, a high school teacher in Virginia, adopted my book and translated it into Python. He sent me a copy of his translation, and I had the unusual experience of learning Python by reading my own book.

Jeff and I revised the book, incorporated a case study by Chris Meyers, and in 2001 we released How to Think Like a Computer Scientist: Learning with Python, also under the GNU Free Documentation License. As Green Tea Press, I published the book and started selling hard copies through Amazon.com and college book stores. Other books from Green Tea Press are available at greenteapress.com.

In 2003, I started teaching at Olin College and I got to teach Python for the first time. The contrast with Java was striking.Students struggled less, learned more, worked on more interesting projects, and generally had a lot more fun.

Over the last five years I have continued to develop the book, correcting errors, improving some of the examples and adding material, especially exercises. In 2008 I started work on a major revision—at the same time, I was contacted by an editor at Cambridge University Press who was interested in publishing the next edition. Good timing!

The result is this book, now with the less grandiose title Think Python. Some of the changes are:

  • I added a section about debugging at the end of each chapter. These sections present general techniques for finding and avoiding bugs, and warnings about Python pitfalls.
  • I removed the material in the last few chapters about the implementation of lists and trees. I still love those topics, but I thought they were incongruent with the rest of the book.
  • I added more exercises, ranging from short tests of understanding to a few substantial projects.
  • I added a series of case studies—longer examples with exercises, solutions, and discussion. Some of them are based on Swampy, a suite of Python programs I wrote for use in my classes. Swampy, code examples, and some solutions are available from thinkpython.com.
  • I expanded the discussion of programming development plans and basic design patterns.
  • The use of Python is more idiomatic. The book is still about programming, not Python, but now I think the book gets more leverage from the language.

I hope you enjoy working with this book, and that it helps you learn to program and think, at least a little bit, likea computer scientist.

Allen B. Downey
Needham MA

Allen Downey is an Associate Professor of Computer Science at the Franklin W. Olin College of Engineering.

Acknowledgements[edit]

First and most importantly, I thank Jeff Elkner, whotranslated my Java book into Python, which got this projectstarted and introduced me to what has turned out to be myfavorite language.

I also thank Chris Meyers, who contributed several sectionsto How to Think Like a Computer Scientist.

And I thank the Free Software Foundation for developingthe GNU Free Documentation License, which helped makemy collaboration with Jeff and Chris possible.

I also thank the editors at Lulu who worked onHow to Think Like a Computer Scientist.

I thank all the students who worked with earlierversions of this book and all the contributors (listedbelow) who sent in corrections and suggestions.

And I thank my wife, Lisa, for her work on this book, and GreenTea Press, and everything else, too.

Contributor List[edit]

More than 100 sharp-eyed and thoughtful readers have sent insuggestions and corrections over the past few years. Theircontributions, and enthusiasm for this project, have been ahuge help.

If you have a suggestion or correction, please send email to feedback@thinkpython.com. If I make a change based on yourfeedback, I will add you to the contributor list(unless you ask to be omitted).

If you include at least part of the sentence theerror appears in, that makes it easy for me to search. Page andsection numbers are fine, too, but not quite as easy to work with.Thanks!

  • Lloyd Hugh Allen sent in a correction to Section 8.4.
  • Yvon Boulianne sent in a correction of a semantic error in Chapter 5.
  • Fred Bremmer submitted a correction in Section 2.1.
  • Jonah Cohen wrote the Perl scripts to convert the LaTeX source for this book into beautiful HTML.
  • 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.
  • Benoit Girard sent in a correction to a humorous mistake in Section 5.6.
  • Courtney Gleason and Katherine Smith wrote horsebet.py, which was used as a case study in an earlier version of the book. Their program can now be found on the website.
  • 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.
  • James Kaylin is a student using the text. He has submitted numerous corrections.
  • David Kershaw fixed the broken catTwice function in Section 3.10.
  • 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.
  • Man-Yong Lee sent in a correction to the example code in Section 2.4.
  • David Mayo pointed out that the word 'unconsciously' in Chapter 1 needed to be changed to 'subconsciously'.
  • Chris McAloon sent in several corrections to Sections 3.9 and 3.10.
  • Matthew J. Moelter has been a long-time contributor who sent in numerous corrections and suggestions to the book.
  • Simon Dicon Montford reported a missing function definition and several typos in Chapter 3. He also found errors in the increment

function in Chapter 13.

  • John Ouzts corrected the definition of 'return value' in Chapter 3.
  • Kevin Parks sent in valuable comments and suggestions as to how to improve the distribution of the book.
  • David Pool sent in a typo in the glossary of Chapter 1, as well as kind words of encouragement.
  • Michael Schmitt sent in a correction to the chapter on files and exceptions.
  • Robin Shaw pointed out an error in Section 13.1, where the printTime function was used in an example without being defined.
  • Paul Sleigh found an error in Chapter 7 and a bug in Jonah Cohen’s Perl script that generates HTML from LaTeX.
  • Craig T. Snydal is testing the text in a course at Drew University. He has contributed several valuable suggestions and corrections.
  • 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 made numerous corrections and suggestions.
  • Keith Verheyden sent in a correction in Chapter 3.
  • Peter Winstanley let us know about a longstanding error in our Latin in Chapter 3.
  • Chris Wrobel made corrections to the code in the chapter on file I/O and exceptions.
  • 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.

  • Christoph Zwerschke sent several corrections and pedagogic suggestions, and explained the difference between gleich and selbe.
  • James Mayer sent us a whole slew of spelling and typographical errors, including two in the contributor list.
  • Hayden McAfee caught a potentially confusing inconsistency between two examples.
  • 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.
  • Tauhidul Hoque and Lex Berezhny created the illustrations in Chapter 1 and improved many of the other illustrations.
  • Dr. Michele Alzetta caught an error in Chapter 8 and sent some interesting pedagogic comments and suggestions about Fibonacci and Old Maid.
  • Andy Mitchell caught a typo in Chapter 1 and a broken example in Chapter 2.
  • Kalin Harvey suggested a clarification in Chapter 7 and caught some typos.
  • Christopher P. Smith caught several typos and is helping us prepare to update the book for Python 2.2.
  • David Hutchins caught a typo in the Foreword.
  • 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.
  • Julie Peters caught a typo in the Preface.
  • Florin Oprina sent in an improvement in makeTime, a correction in printTime, and a nice typo.
  • D. J. Webre suggested a clarification in Chapter 3.
  • Ken found a fistful of errors in Chapters 8, 9 and 11.
  • Ivo Wever caught a typo in Chapter 5 and suggested a clarification in Chapter 3.
  • Curtis Yanko suggested a clarification in Chapter 2.
  • Ben Logan sent in a number of typos and problems with translating the book into HTML.
  • Jason Armstrong saw the missing word in Chapter 2.
  • Louis Cordier noticed a spot in Chapter 16 where the code didn't match the text.
  • Brian Cain suggested several clarifications in Chapters 2 and 3.
  • Rob Black sent in a passel of corrections, including some changes for Python 2.2.
  • Jean-Philippe Rey at Ecole Centrale Paris sent a number of patches, including some updates for Python 2.2 and other thoughtful improvements.
  • Jason Mader at George Washington University made a number of useful suggestions and corrections.
  • Jan Gundtofte-Bruun reminded us that “a error” is an error.
  • Abel David and Alexis Dinno reminded us that the plural of “matrix” is “matrices”, not “matrixes”. This error was in the book for years, but two readers with the same initials reported it on the same day. Weird.
  • Charles Thayer encouraged us to get rid of the semi-colons we had put at the ends of some statements and to clean up our use of “argument” and “parameter”.
  • Roger Sperberg pointed out a twisted piece of logic in Chapter 3.
  • Sam Bull pointed out a confusing paragraph in Chapter 2.
  • Andrew Cheung pointed out two instances of “use before def.”
  • C. Corey Capel spotted the missing word in the Third Theorem of Debugging and a typo in Chapter 4.
  • Alessandra helped clear up some Turtle confusion.
  • Wim Champagne found a brain-o in a dictionary example.
  • Douglas Wright pointed out a problem with floor division in arc.
  • Jared Spindor found some jetsam at the end of a sentence.
  • Lin Peiheng sent a number of very helpful suggestions.
  • Ray Hagtvedt sent in two errors and a not-quite-error.
  • Torsten Hübsch pointed out an inconsistency in Swampy.
  • Inga Petuhhov corrected an example in Chapter 14.
  • Arne Babenhauserheide sent several helpful corrections.
  • Mark E. Casida is is good at spotting repeated words.
  • Scott Tyler filled in a that was missing. And then sent in a heap of corrections.
  • Gordon Shephard sent in several corrections, all in separate emails.
  • Andrew Turner spotted an error in Chapter 8.
  • Adam Hobart fixed a problem with floor division in arc.
  • Daryl Hammond and Sarah Zimmerman pointed out that I served up math.pi too early. And Zim spotted a typo.
  • George Sass found a bug in a Debugging section.
  • Brian Bingham suggested Exercise 11.9.
  • Leah Engelbert-Fenton pointed out that I used tuple as a variable name, contrary to my own advice. And then found a bunch of typos and a “use before def.”
  • Joe Funke spotted a typo.
  • Chao-chao Chen found an inconsistency in the Fibonacci example.
  • Jeff Paine knows the difference between space and spam.
  • Lubos Pintes sent in a typo.
  • Gregg Lind and Abigail Heithoff suggested Exercise 14.6.
  • Max Hailperin pointed out a change coming in Python 3.0. Max is one of the authors of the extraordinary Concrete Abstractions, which you might want to read when you are done with this book.
  • Chotipat Pornavalai found an error in an error message.
  • Stanislaw Antol sent a list of very helpful suggestions.
  • Eric Pashman sent a number of corrections for Chapters 4–11.
  • Miguel Azevedo found some typos.
  • Jianhua Liu sent in a long list of corrections.
  • Nick King found a missing word.
  • Martin Zuther sent a long list of suggestions.
  • Adam Zimmerman found an inconsistency in my instance of an “instance” and several other errors.
  • Ratnakar Tiwari suggested a footnote explaining degenerate triangles.
  • Anurag Goel suggested another solution for is_abecedarian and sent some additional corrections. And he knows how to spell Jane Austen.
  • Kelli Kratzer spotted one of they typos.
  • Mark Griffiths pointed out a confusing example in Chapter 3.
  • Roydan Ongie found an error in my Newton’s method.

The further strange adventures of this book[edit]

In September of 2008, Whiteknight converted the HTML version of 'Think Python' at Green Tea Press[2]to a Wikitext version at Wikibooks[3].Now anyone can improve the text.

  1. 'The strange history of this book'by Allen B. Downey
  2. 'Think Python' at Green Tea Press
  3. Wikibooks: Think Python

The goal of this book is to teach you to think like acomputer scientist. This way of thinking combines some of the best featuresof mathematics, engineering, and natural science. Like mathematicians,computer scientists use formal languages to denote ideas (specificallycomputations). Like engineers, they design things, assembling componentsinto systems and evaluating tradeoffs among alternatives. Like scientists,they observe the behavior of complex systems, form hypotheses, and testpredictions.

The single most important skill for a computer scientist is problem solving. Problem solving means the ability to formulateproblems, think creatively about solutions, and express a solution clearlyand accurately. As it turns out, the process of learning to program is anexcellent opportunity to practice problem-solving skills. That’s whythis chapter is called, “The way of the program.”

On one level, you will be learning to program, a usefulskill by itself. On another level, you will use programming as a means toan end. As we go along, that end will become clearer.

The Python programming language[edit]

The programming language you will learn is Python. Python isan example of a high-level language; other high-level languagesyou might have heard of are C, C++, Perl, and Java.

There are also low-level languages, sometimes referred to as “machinelanguages” or “assembly languages.” Loosely speaking, computerscan only execute programs written in low-level languages. Soprograms written in a high-level language have to be processed beforethey can run. This extra processing takes some time, which is a smalldisadvantage of high-level languages.

The advantages are enormous. First, it is much easier to programin a high-level language. Programs written in a high-level languagetake less time to write, they are shorter and easier to read, and theyare more likely to be correct. Second, high-level languages are portable, meaning that they can run on different kinds of computerswith few or no modifications. Low-level programs can run on only onekind of computer and have to be rewritten to run on another.

Due to these advantages, almost all programs are written in high-levellanguages. Low-level languages are used only for a few specializedapplications.

Two kinds of programs process high-level languagesinto low-level languages: interpreters and compilers.An interpreter reads a high-level program and executes it, meaning that itdoes what the program says. It processes the program a little at a time,alternately reading lines and performing computations.

A compiler reads the program and translates it completely before theprogram starts running. In this context, the high-level program iscalled the source code, and the translated program is called theobject code or the executable. Once a program iscompiled, you can execute it repeatedly without further translation.

Python is considered an interpreted language because Python programsare executed by an interpreter. There are two ways to use theinterpreter: interactive mode and script mode. Ininteractive mode, you type Python programs and the interpreter printsthe result:

The chevron, >>>, is theprompt the interpreter uses to indicate that it is ready. Ifyou type 1 + 1, and then press the Enter key,the interpreter replies 2.

Alternatively, you can store code in a file and use the interpreter toexecute the contents of the file, which is called a script. Byconvention, Python scripts have names that end with .py.

To execute the script, you have to tell the interpreter the name ofthe file. In a UNIX command window, you would type pythondinsdale.py. In other development environments, the details ofexecuting scripts are different. You can find instructions foryour environment at the Python Website python.org.

Working in interactive mode is convenient for testing small pieces ofcode because you can type and execute them immediately. But foranything more than a few lines, you should save your codeas a script so you can modify and execute it in the future.

What is a program?[edit]

A program is a sequence of instructions that specifies how toperform a computation. The computation might be somethingmathematical, such as solving a system of equations or finding theroots of a polynomial, but it can also be a symbolic computation, suchas searching and replacing text in a document or (strangely enough)compiling a program.

The details look different in different languages, but a few basicinstructions appear in just about every language:

input:
Get data from the keyboard, a file, or someother device.
output:
Display data on the screen or send data to afile or other device.
math:
Perform basic mathematical operations like addition andmultiplication.
conditional execution:
Check for certain conditions andexecute the appropriate sequence of statements.
repetition:
Perform some action repeatedly, usually withsome variation.

Believe it or not, that’s pretty much all there is to it. Everyprogram you’ve ever used, no matter how complicated, is made up ofinstructions that look pretty much like these. So you can think ofprogramming as the process of breaking a large, complex taskinto smaller and smaller subtasks until the subtasks aresimple enough to be performed with one of these basic instructions.

That may be a little vague, but we will come back to this topicwhen we talk about algorithms.

What is debugging?[edit]

Programming is error-prone. For whimsical reasons, programming errorsare called bugs and the process of tracking them down is calleddebugging.

Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors. It is usefulto distinguish between them in order to track them down more quickly.

Syntax errors[edit]

Python can only execute a program if the syntax iscorrect; otherwise, the interpreter displays an error message.Syntax refers to the structure of a program and the rules aboutthat structure. For example, parentheses have to come in matching pairs, so(1 + 2) is legal, but 8) is a syntax error.

In English readers can tolerate most syntax errors, which is why wecan read the poetry of E. E. Cummings without spewing error messages.Python is not so forgiving. If there is a single syntax erroranywhere in your program, Python will display an error message and quit,and you will not be able to run your program. During the first fewweeks of your programming career, you will probably spend a lot oftime tracking down syntax errors. As you gain experience, you willmake fewer errors and find them faster.

Runtime errors[edit]

The second type of error is a runtime error, so called because theerror does not appear until after the program has started running.These errors are also called exceptions because they usuallyindicate that something exceptional (and bad) has happened.

Runtime errors are rare in the simple programs you will see in thefirst few chapters, so it might be a while before you encounter one.

Semantic errors[edit]

The third type of error is the semantic error. If there is asemantic error in your program, it will run successfully in the sensethat the computer will not generate any error messages, but it willnot do the right thing. It will do something else. Specifically, itwill do what you told it to do.

The problem is that the program you wrote is not the program youwanted to write. The meaning of the program (its semantics) is wrong.Identifying semantic errors can be tricky because it requires you to workbackward by looking at the output of the program and trying to figureout what it is doing.

Experimental debugging[edit]

One of the most important skills you will acquire is debugging.Although it can be frustrating, debugging is one of the mostintellectually rich, challenging, and interesting parts ofprogramming.

In some ways, debugging is like detective work. You are confrontedwith clues, and you have to infer the processes and events that ledto the results you see.

Debugging is also like an experimental science. Once you have an ideaabout what is going wrong, you modify your program and try again. Ifyour hypothesis was correct, then you can predict the result of themodification, and you take a step closer to a working program. Ifyour hypothesis was wrong, you have to come up with a new one. AsSherlock Holmes pointed out, “When you have eliminated theimpossible, whatever remains, however improbable, must be the truth.”(A. Conan Doyle, The Sign of Four)

For some people, programming and debugging are the same thing. Thatis, programming is the process of gradually debugging a program untilit does what you want. The idea is that you should start with aprogram that does something and make small modifications,debugging them as you go, so that you always have a working program.

For example, Linux is an operating system that contains thousands oflines of code, but it started out as a simple program Linus Torvaldsused to explore the Intel 80386 chip. According to Larry Greenfield,“One of Linus’s earlier projects was a program that would switchbetween printing AAAA and BBBB. This later evolved to Linux.”(The Linux Users’ Guide Beta Version 1).

Later chapters will make more suggestions about debugging and otherprogramming practices.

Formal and natural languages[edit]

Natural languages are the languages people speak, such as English, Spanish, and French. They were not designed by people (although people try to impose some order on them); they evolved naturally.

Exercise

Formal languages are languages that are designed by people forspecific applications. For example, the notation that mathematiciansuse is a formal language that is particularly good at denotingrelationships among numbers and symbols. Chemists use a formallanguage to represent the chemical structure of molecules. Andmost importantly:

Programming languages are formal languages that have been designed to express computations.

Formal languages tend to have strict rules about syntax. For example,3 + 3 = 6 is a syntactically correct mathematical statement, but 3 + = 3 $ 6 is not. H2O is a syntactically correctchemical formula, but 2Zz is not.

Syntax rules come in two flavors, pertaining to tokens andstructure. Tokens are the basic elements of the language, such aswords, numbers, and chemical elements. One of the problems with 3 += 3 $ 6 is that $ is not a legal token in mathematics(at least as far as I know). Similarly, 2Zz is not legal becausethere is no element with the abbreviation Zz.

The second type of syntax error pertains to the structure of astatement; that is, the way the tokens are arranged. The statement 3+ = 3 $ 6 is illegal because even though + and = arelegal tokens, you can’t have one right after the other. Similarly,in a chemical formula the subscript comes after the element name, notbefore.

Exercise 1

Write a well-structured Englishsentence with invalid tokens in it. Then write another sentencewith all valid tokens but with invalid structure.

When you read a sentence in English or a statement in a formallanguage, you have to figure out what the structure of the sentence is(although in a natural language you do this subconsciously). Thisprocess is called parsing.

For example, when you hear the sentence, “The penny dropped,” youunderstand that “the penny” is the subject and “dropped” is thepredicate. Once you have parsed a sentence, you can figure out what itmeans, or the semantics of the sentence. Assuming that you knowwhat a penny is and what it means to drop, you will understand thegeneral implication of this sentence.

Although formal and natural languages have many features incommon—tokens, structure, syntax, and semantics—there are somedifferences:

ambiguity:
Natural languages are full of ambiguity, whichpeople deal with by using contextual clues and other information.Formal languages are designed to be nearly or completely unambiguous,which means that any statement has exactly one meaning,regardless of context.
redundancy:
In order to make up for ambiguity and reducemisunderstandings, natural languages employ lots ofredundancy. As a result, they are often verbose. Formal languagesare less redundant and more concise.
literalness:
Natural languages are full of idiom and metaphor.If I say, “The penny dropped,” there is probably no penny andnothing dropping[1]. Formal languagesmean exactly what they say.

People who grow up speaking a natural language—everyone—often have ahard time adjusting to formal languages. In some ways, the differencebetween formal and natural language is like the difference betweenpoetry and prose, but more so:

Poetry:
Words are used for their sounds as well as fortheir meaning, and the whole poem together creates an effect oremotional response. Ambiguity is not only common but oftendeliberate.
Prose:
The literal meaning of words is more important,and the structure contributes more meaning. Prose is more amenable toanalysis than poetry but still often ambiguous.
Programs:
The meaning of a computer program is unambiguousand literal, and can be understood entirely by analysis of thetokens and structure.

Here are some suggestions for reading programs (and other formallanguages). First, remember that formal languages are much more densethan natural languages, so it takes longer to read them. Also, thestructure is very important, so it is usually not a good idea to readfrom top to bottom, left to right. Instead, learn to parse theprogram in your head, identifying the tokens and interpreting thestructure. Finally, the details matter. Small errors inspelling and punctuation, which you can get awaywith in natural languages, can make a big difference in a formallanguage.

The first program[edit]

Traditionally, the first program you write in a new languageis called “Hello, World!” because all it does is display thewords, “Hello, World!” In Python, it looks like this:

This is an example of a print statement[2], whichdoesn’t actually print anything on paper. It displays a value on thescreen. In this case, the result is the words

The quotation marks in the program mark the beginning and endof the text to be displayed; they don’t appear in the result.

Some people judge the quality of a programming language by thesimplicity of the “Hello, World!” program. By this standard, Pythondoes about as well as possible.

Debugging[edit]

It is a good idea to read this book in front of a computer so you cantry out the examples as you go. You can run most of the examples ininteractive mode, but if you put the code into a script, it is easierto try out variations.

Whenever you are experimenting with a new feature, you should tryto make mistakes. For example, in the “Hello, world!” program,what happens if you leave out one of the quotation marks? Whatif you leave out both? What if you spell print wrong?

This kind of experiment helps you remember what you read; it also helpswith debugging, because you get to know what the error messages mean.It is better to make mistakes now and on purpose than laterand accidentally.

Programming, and especially debugging, sometimes brings out strongemotions. If you are struggling with a difficult bug, you might feel angry, despondent or embarrassed.

There is evidence that people naturally respond to computers as ifthey were people[3]. When they work well, we thinkof them as teammates, and when they are obstinate or rude, werespond to them the same way we respond to rude,obstinate people.

Preparing for these reactions might help you deal with them.One approach is to think of the computer as an employee withcertain strengths, like speed and precision, andparticular weaknesses, like lack of empathy and inabilityto grasp the big picture.

Your job is to be a good manager: find ways to take advantageof the strengths and mitigate the weaknesses. And find waysto use your emotions to engage with the problem,without letting your reactions interfere with your abilityto work effectively.

Learning to debug can be frustrating, but it is a valuable skillthat is useful for many activities beyond programming. At theend of each chapter there is a debugging section, like this one,with my thoughts about debugging. I hope they help!

Glossary[edit]

problem solving:
The process of formulating a problem, findinga solution, and expressing the solution.
high-level language:
A programming language like Python thatis designed to be easy for humans to read and write.
low-level language:
A programming language that is designedto be easy for a computer to execute; also called “machine language” or“assembly language.”
portability:
A property of a program that can run on morethan one kind of computer.
interpret:
To execute a program in a high-level languageby translating it one line at a time.
compile:
To translate a program written in a high-level languageinto a low-level language all at once, in preparation for laterexecution.
source code:
A program in a high-level language beforebeing compiled.
object code:
The output of the compiler after it translatesthe program.
executable:
Another name for object code that is readyto be executed.
prompt:
Characters displayed by the interpreter to indicatethat it is ready to take input from the user.
script:
A program stored in a file (usually one that will beinterpreted).
interactive mode:
A way of using the Python interpreter bytyping commands and expressions at the prompt.
script mode:
A way of using the Python interpreter to readand execute statements in a script.
program:
A set of instructions that specifies a computation.
algorithm:
A general process for solving a category ofproblems.
bug:
An error in a program.
debugging:
The process of finding and removing any of thethree kinds of programming errors.
syntax:
The structure of a program.
syntax error:
An error in a program that makes it impossibleto parse (and therefore impossible to interpret).
exception:
An error that is detected while the program is running.
semantics:
The meaning of a program.
semantic error:
An error in a program that makes it do somethingother than what the programmer intended.
natural language:
Any one of the languages that people speak thatevolved naturally.
formal language:
Any one of the languages that people have designedfor specific purposes, such as representing mathematical ideas orcomputer programs; all programming languages are formal languages.
token:
One of the basic elements of the syntactic structure ofa program, analogous to a word in a natural language.
parse:
To examine a program and analyze the syntactic structure.
print statement:
An instruction that causes the Pythoninterpreter to display a value on the screen.

Exercises[edit]

Exercise 2[edit]

Use a web browser to go to the Python website, http://python.org/.This page contains information about Python and linksto Python-related pages, and it gives you the ability to searchthe Python documentation.For example, if you enter print in the search window, thefirst link that appears is the documentation of the printstatement. At this point, not all of it will make sense to you,but it is good to know where it is.

Exercise 3[edit]

Start the Python interpreter and type 'help()' to start the onlinehelp utility. Or you can type help('print') to get informationabout the 'print' statement.If this example doesn’t work, youmay need to install additional Python documentation or set anenvironment variable; the details depend on your operating system andversion of Python.

Exercise 4[edit]

Start the Python interpreter and use it as a calculator.Python’s syntax for math operations is almost the same asstandard mathematical notation. For example, the symbols'+', '-' and '/' denote addition, subtractionand division, as you would expect. The symbol formultiplication is '*'.If you run a 10 kilometer race in 43 minutes 30 seconds, what is youraverage time per mile? What is your average speed in miles per hour?(Hint: there are 1.61 kilometers in a mile).

References[edit]

  1. This idiom means that someone realized somethingafter a period of confusion.
  2. In Python 3.0,print is a function, not a statement, so the syntax is print(’Hello, World!’). We will get to functions soon!
  3. See Reeves and Nass, The MediaEquation: How People Treat Computers, Television, and New MediaLike Real People and Places.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Values and types[edit]

A value is one of the basic things a program works with, like a letter or a number. The values we have seen so far are 1, 2, and 'Hello, World!'.

These values belong to different types:2 is an integer, and 'Hello, World!' is a string,so-called because it contains a “string” of letters.You (and the interpreter) can identifystrings because they are enclosed in quotation marks.

The print statement also works for integers.

If you are not sure what type a value has, the interpreter can tell you.

Not surprisingly, strings belong to the type str andintegers belong to the type int. Less obviously, numberswith a decimal point belong to a type called float,because these numbers are represented in aformat called floating-point.

What about values like '17' and '3.2'?They look like numbers, but they are in quotation marks likestrings.

They're strings.

When you type a large integer, you might be tempted to use commasbetween groups of three digits, as in 1,000,000. This is not alegal integer in Python, but it is legal:

Well, that’s not what we expected at all! Python interprets 1,000,000 as a comma-separated sequence of integers, which itprints with spaces between.

This is the first example we have seen of a semantic error: the coderuns without producing an error message, but it doesn't do the“right” thing.

Variables[edit]

One of the most cheese cake features of a programming language is theability to manipulate variables. A variable is a name thatrefers to a value.

An assignment statement creates new variables and givesthem values:

This example makes three assignments. The first assigns a stringto a new variable named message;the second gives the integer 17 to n; the thirdassigns the (approximate) value of π to pi.

A common way to represent variables on paper is to write the name withan arrow pointing to the variable’s value. This kind of figure iscalled a state diagram because it shows what state each of thevariables is in (think of it as the variable’s state of mind).This diagram shows the result of the previous example:

message{displaystyle rightarrow }'And now for something completely different'
n{displaystyle rightarrow }17
pi{displaystyle rightarrow }3.1415926535897931

To display the value of a variable, you can use a print statement:

The type of a variable is the type of the value it refers to.

Exercise 1[edit]

If you type an integer with a leading zero, you might geta confusing error:

Other number seem to work, but the results are bizarre:

Can you figure out what is going on? Hint: print the values 01, 010, 0100 and 01000.

Variable names and keywords[edit]

Programmers generally choose names for their variables that are meaningful—they document what the variable is used for.

Variable names can be arbitrarily long. They can contain both letters and numbers, but they have to begin with a letter. It is legal to use uppercase letters, but it is a good idea to begin variable names with a lowercase letter (you'll see why later).

The underscore character (_) can appear in a name. It is often used in names with multiple words, such as my_name or airspeed_of_unladen_swallow.

If you give a variable an illegal name, you get a syntax error:

76trombones is illegal because it does not begin with a letter.more@ is illegal because it contains an illegal character, @. But what's wrong with class?

It turns out that class is one of Python's keywords. Theinterpreter uses keywords to recognize the structure of the program,and they cannot be used as variable names.

Python has 31 keywords:

anddelfromnotwhile
aselifglobalorwith
assertelseifpassyield
breakexceptimportprint
classexecinraise
continuefinallyisreturn
defforlambdatry

You might want to keep this list handy. If the interpreter complainsabout one of your variable names and you don't know why, see if itis on this list.

If you write your code in a text editor that understands Python, you may find that it makes it easy for you to spot such keyword clashes by displaying keywords in a different color to ordinary variables. This feature is called syntax highlighting, and most programmers find it indispensable. This book uses syntax highlighting for its example code, so in the following example:

you can see that yield has been recognized as a keyword and not as an ordinary variable, since it is colored orange.

Statements[edit]

A statement is a unit of code that the Python interpreter canexecute. We have seen two kinds of statements: printand assignment.

When you type a statement in interactive mode, the interpreterexecutes it and displays the result, if there is one.

A script usually contains a sequence of statements. If thereis more than one statement, the results appear one at a timeas the statements execute.

For example, the script

produces the output

The assignment statement produces no output.

Operators and operands[edit]

Operators are special symbols that represent computations likeaddition and multiplication. The values the operator is applied toare called operands.

The operators +, -, *, / and **perform addition, subtraction, multiplication, division andexponentiation, as in the following examples:

In some other languages, ^ is used for exponentiation, butin Python it is a bitwise operator called XOR. I won’t coverbitwise operators in this book, but you can read aboutthem at wiki.python.org/moin/BitwiseOperators.

The division operator might not do what you expect:

The value of minute is 59, and in conventional arithmetic 59divided by 60 is 0.98333, not 0. The reason for the discrepancy isthat Python is performing floor division.[1]

When both of the operands are integers, the result is also aninteger; floor division chops off the fractionpart, so in this example it rounds down to zero.

If either of the operands is a floating-point number, Python performsfloating-point division, and the result is a float:

Expressions[edit]

An expression is a combination of values, variables, and operators.A value all by itself is considered an expression, and so isa variable, so the following are all legal expressions(assuming that the variable x has been assigned a value):

If you type an expression in interactive mode, the interpreterevaluates it and displays the result:

But in a script, an expression all by itself doesn’tdo anything! This is a commonsource of confusion for beginners.

Exercise 2[edit]

Type the following statements in the Python interpreter to see what they do:

Now put the same statements into a script and run it. What is the output? Modify the script by transforming each expression into a print statement and then run it again.

Order of operations[edit]

When more than one operator appears in an expression, the order ofevaluation depends on the rules of precedence. Formathematical operators, Python follows mathematical convention.The acronym PEMDAS is a useful way toremember the rules:

  • Parentheses have the highest precedence and can be used to force an expression to evaluate in the order you want. Since expressions in parentheses are evaluated first, 2 * (3-1) is 4, and (1+1)**(5-2) is 8. You can also use parentheses to make an expression easier to read, as in (minute * 100) / 60, even if it doesn't change the result.
  • Exponentiation has the next highest precedence, so 2**1+1 is 3, not 4, and 3*1**3 is 3, not 27.
  • Multiplication and Division have the same precedence, which is higher than Addition and Subtraction, which also have the same precedence. So 2*3-1 is 5, not 4, and 6+4/2 is 8, not 5.
  • Operators with the same precedence are evaluated from left to right. So in the expression degrees / 2 * pi, the division happens first and the result is multiplied by pi. To divide by 2 π, you can reorder the operands or use parentheses.

String operations[edit]

In general, you cannot perform mathematical operations on strings, evenif the strings look like numbers, so the following are illegal:

The + operator works with strings, but itmight not do what you expect: it performsconcatenation, which means joining the strings bylinking them end-to-end. For example:

The output of this program is throatwarbler.

The * operator also works on strings; it performs repetition.For example, ’Spam’*3 is 'SpamSpamSpam'. If one of the operandsis a string, the other has to be an integer.

This use of + and * makes sense byanalogy with addition and multiplication. Just as 4*3 isequivalent to 4+4+4, we expect 'Spam'*3 to be the same as'Spam'+'Spam'+'Spam', and it is. On the other hand, there is asignificant way in which string concatenation and repetition aredifferent from integer addition and multiplication.Can you think of a property that addition hasthat string concatenation does not?

Comments[edit]

As programs get bigger and more complicated, they get more difficultto read. Formal languages are dense, and it is often difficult tolook at a piece of code and figure out what it is doing, or why.

For this reason, it is a good idea to add notes to your programs to explainin natural language what the program is doing. These notes are calledcomments, and they start with the # symbol:

In this case, the comment appears on a line by itself. You can also put comments at the end of a line:

Everything from the # to the end of the line is ignored—ithas no effect on the program.

Comments are most useful when they document non-obvious features ofthe code. It is reasonable to assume that the reader can figure outwhat the code does; it is much more useful to explain why.

This comment is redundant with the code and useless:

This comment contains useful information that is not in the code:

Good variable names can reduce the need for comments, but long names can make complex expressions hard to read, so there is a tradeoff.

Debugging[edit]

At this point the syntax error you are most likely to make isan illegal variable name, like class and yield, whichare keywords, or odd~job and US$, which containillegal characters.

If you put a space in a variable name, Python thinks it is twooperands without an operator:

For syntax errors, the error messages don’t help much.The most common messages are SyntaxError: invalid syntax andSyntaxError: invalid token, neither of which is very informative.

The runtime error you are most likely to make is a “use beforedef;” that is, trying to use a variable before you have assigneda value. This can happen if you spell a variable name wrong:

Variables names are case sensitive, so LaTeX is not thesame as latex.

At this point the most likely cause of a semantic error isthe order of operations. For example, to evaluate 1/2 π,you might be tempted to write

But the division happens first, so you would get π / 2, whichis not the same thing! There is no way for Pythonto know what you meant to write, so in this case you don’tget an error message; you just get the wrong answer.

Glossary[edit]

value:
One of the basic units of data, like a number or string, that a program manipulates.
type:
A category of values. The types we have seen so farare integers (type int), floating-point numbers (type float), and strings (type str).
integer:
A type that represents whole numbers.
floating-point:
A type that represents numbers with fractionalparts.
string:
A type that represents sequences of characters.
variable:
A name that refers to a value.
statement:
A section of code that represents a command or action. Sofar, the statements we have seen are assignments and print statements.
assignment:
A statement that assigns a value to a variable.
state diagram:
A graphical representation of a set of variables and thevalues they refer to.
keyword:
A reserved word that is used by the compiler to parse aprogram; you cannot use keywords like if, def, and while asvariable names.
operator:
A special symbol that represents a simple computation likeaddition, multiplication, or string concatenation.
operand:
One of the values on which an operator operates.
floor division:
The operation that divides two numbers and chops offthe fraction part.
expression:
A combination of variables, operators, and values thatrepresents a single result value.
evaluate:
To simplify an expression by performing the operationsin order to yield a single value.
rules of precedence:
The set of rules governing the order in whichexpressions involving multiple operators and operands are evaluated.
concatenate:
To join two operands end-to-end.
comment:
Information in a program that is meant for otherprogrammers (or anyone reading the source code) and has no effect on theexecution of the program.

Exercises[edit]

Exercise 3[edit]

Assume that we execute the following assignment statements:

For each of the following expressions, write the value of the expression and the type (of the value of the expression).

Use the Python interpreter to check your answers.

Exercise 4[edit]

Practice using the Python interpreter as a calculator:

  • The volume of a sphere with radius 'r' is '4/3' π r3.

What is the volume of a sphere with radius 5? Hint: 392.6 is wrong!

  • Suppose the cover price of a book is $24.95, but bookstores get a

40% discount. Shipping costs $3 for the first copy and 75 centsfor each additional copy. What is the total wholesale cost for60 copies?

  • If I leave my house at 6:52 am and run 1 mile at an easy pace

(8:15 per mile), then 3 miles at tempo (7:12 per mile) and 1 mile ateasy pace again, what time do I get home for breakfast?

Notes[edit]

  1. In Python 3.0,the result of this division is a float. The new operator// performs integer division.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Function calls[edit]

In the context of programming, a function is a named sequence ofstatements that performs a computation. When you define a function,you specify the name and the sequence of statements. Later, you can'call' the function by name. We have already seen one example of a function call:


The name of the function is type. The expression in parenthesesis called the argument of the function. The result, for thisfunction, is the type of the argument.

It is common to say that a function 'takes' an argument and 'returns' a result. The result is called the return value.

Type conversion functions[edit]

Python provides built-in functions that convert valuesfrom one type to another. The int function takes any value andconverts it to an integer, if it can, or complains otherwise:

int can convert floating-point values to integers, but itdoesn't round off; it chops off the fraction part:

float converts integers and strings to floating-pointnumbers:

Finally, str converts its argument to a string:

Math functions[edit]

Python has a math module that provides most of the familiarmathematical functions. A module is a file that contains acollection of related functions.


Before we can use the module, we have to import it:

This statement creates a module object named math. Ifyou print the module object, you get some information about it:


The module object contains the functions and variables defined in themodule. To access one of the functions, you have to specify the nameof the module and the name of the function, separated by a dot (alsoknown as a period). This format is called dot notation.


The first example computes the logarithm base 10 of thesignal-to-noise ratio. The math module also provides afunction called log that computes logarithms base e.


The second example finds the sine of radians. The name of thevariable is a hint that sin and the other trigonometricfunctions (cos, tan, etc.) take arguments in radians. Toconvert from degrees to radians, divide by 360 and multiply by 2π:


The expression math.pi gets the variable pi from the mathmodule. The value of this variable is an approximationof π, accurate to about 15 digits.


If you knowyour trigonometry, you can check the previous result by comparing it tothe square root of two divided by two:


Composition[edit]

So far, we have looked at the elements of a program—variables,expressions, and statements—in isolation, without talking about how tocombine them.

One of the most useful features of programming languages is theirability to take small building blocks and compose them. Forexample, the argument of a function can be any kind of expression,including arithmetic operators:

And even function calls:


Almost anywhere you can put a value, you can put an arbitraryexpression, with one exception: the left side of an assignmentstatement has to be a variable name. Any other expression on the leftside is a syntax error.

Adding new functions[edit]

So far, we have only been using the functions that come with Python,but it is also possible to add new functions.A function definition specifies the name of a new function andthe sequence of statements that execute when the function is called.

Here is an example:

def is a keyword that indicates that this is a functiondefinition. The name of the function is print_lyrics. Therules for function names are the same as for variable names: letters,numbers and some punctuation marks are legal, but the first charactercan't be a number. You can't use a keyword as the name of a function,and you should avoid having a variable and a function with the samename.

The empty parentheses after the name indicate that this functiondoesn't take any arguments.

The first line of the function definition is called the header;the rest is called the body. The header has to end with a colonand the body has to be indented. By convention, the indentation isalways four spaces (see Section ). The body can containany number of statements.

The strings in the print statements are enclosed in doublequotes. Single quotes and double quotes do the same thing;most people use single quotes except in cases like this wherea single quote (which is also an apostrophe) appears in the string.

If you type a function definition in interactive mode, the interpreterprints ellipses (...) to let you know that the definitionisn't complete:

To end the function, you have to enter an empty line (this isnot necessary in a script).

Books Never Written Math Beginning Your Exercise Program By Year

Defining a function creates a variable with the same name.

The value of print_lyrics is a function object, whichhas type 'function'.


The syntax for calling the new function is the same asfor built-in functions:


Once you have defined a function, you can use it inside anotherfunction. For example, to repeat the previous refrain, we could writea function called repeat_lyrics:


And then call repeat_lyrics:


But that's not really how the song goes.


Definitions and uses[edit]

Pulling together the code fragments from the previous section, thewhole program looks like this:


This program contains two function definitions: print_lyrics andrepeat_lyrics. Function definitions get executed just like otherstatements, but the effect is to create function objects. The statementsinside the function do not get executed until the function is called, andthe function definition generates no output.


As you might expect, you have to create a function before you canexecute it. In other words, the function definition has to beexecuted before the first time it is called.

Exercise 1[edit]

Move the last line of this programto the top, so the function call appears before the definitions. Run the program and see what errormessage you get.

Exercise 2[edit]

Move the function call back to the bottomand move the definition of print_lyrics after the definition ofrepeat_lyrics. What happens when you run this program?

Flow of execution[edit]

In order to ensure that a function is defined before its first use,you have to know the order in which statements are executed, which iscalled the flow of execution.

Execution always begins at the first statement of the program.Statements are executed one at a time, in order from top to bottom.

Function definitions do not alter the flow of execution of theprogram, but remember that statements inside the function are notexecuted until the function is called.

A function call is like a detour in the flow of execution. Instead ofgoing to the next statement, the flow jumps to the body ofthe function, executes all the statements there, and then comes backto pick up where it left off.

That sounds simple enough, until you remember that one function cancall another. While in the middle of one function, the program mighthave to execute the statements in another function. But whileexecuting that new function, the program might have to execute yetanother function!

Fortunately, Python is good at keeping track of where it is, so eachtime a function completes, the program picks up where it left off inthe function that called it. When it gets to the end of the program,it terminates.


What's the moral of this sordid tale? When you read a program, youdon't always want to read from top to bottom. Sometimes it makesmore sense if you follow the flow of execution.


Parameters and arguments[edit]

Some of the built-in functions we have seen require arguments. Forexample, when you call math.sin you pass a numberas an argument. Some functions take more than one argument:math.pow takes two, the base and the exponent.


Inside the function, the arguments are assigned tovariables called parameters. Here is an example of auser-defined function that takes an argument:


This function assigns the argument to a parameternamed bruce. When the function is called, it prints the value ofthe parameter (whatever it is) twice.


This function works with any value that can be printed.


The same rules of composition that apply to built-in functions alsoapply to user-defined functions, so we can use any kind of expressionas an argument for print_twice:


The argument is evaluated before the function is called, soin the examples the expressions 'Spam '*4 andmath.cos(math.pi) are only evaluated once.


You can also use a variable as an argument:


The name of the variable we pass as an argument (michael) hasnothing to do with the name of the parameter (bruce). Itdoesn't matter what the value was called back home (in the caller);here in print_twice, we call everybody bruce.


Variables and parameters are local[edit]

When you create a variable inside a function, it is local,which means that it onlyexists inside the function. For example:


This function takes two arguments, concatenates them, and printsthe result twice. Here is an example that uses it:


When cat_twice terminates, the variable catis destroyed. If we try to print it, we get an exception:


Parameters are also local.For example, outside print_twice, there is nosuch thing as bruce.


Stack diagrams[edit]

To keep track of which variables can be used where, it is sometimesuseful to draw a stack diagram. Like state diagrams, stackdiagrams show the value of each variable, but they also show thefunction each variable belongs to.


Each function is represented by a frame. A frame is a boxwith the name of a functionbeside it and the parameters and variables of the function inside it.The stack diagram for theprevious example looks like this:

File:Book004.pngThe frames are arranged in a stack that indicates which functioncalled which, and so on. In this example, print_twice

was called by cat_twice, and cat_twice was called by __main__, which is a special name for the topmost frame. Whenyou create a variable outside of any function, it belongs to __main__.


Each parameter refers to the same value as its correspondingargument. So, part1 has the same value asline1, part2 has the same value as line2,and bruce has the same value as cat.


If an error occurs during a function call, Python prints thename of the function, and the name of the function that calledit, and the name of the function that called that, all theway back to __main__.


For example, if you try to access cat from within

print_twice, you get a NameError:


This list of functions is called a traceback. It tells you whatprogram file the error occurred in, and what line, and what functionswere executing at the time. It also shows the line of code thatcaused the error.


The order of the functions in the traceback is the same as theorder of the frames in the stack diagram. The function that iscurrently running is at the bottom.


Fruitful functions and void functions[edit]

Some of the functions we are using, such as the math functions, yieldresults; for lack of a better name, I call them fruitfulfunctions. Other functions, like print_twice, perform anaction but don't return a value. They are called voidfunctions.


When you call a fruitful function, you almost alwayswant to do something with the result; for example, you mightassign it to a variable or use it as part of an expression:


When you call a function in interactive mode, Python displaysthe result:


But in a script, if you call a fruitful function all by itself,the return value is lost forever!


This script computes the square root of 5, but since it doesn't storeor display the result, it is not very useful.


Void functions might display something on the screen or have someother effect, but they don't have a return value. If you try toassign the result to a variable, you get a special value calledNone.


The value None is not the same as the string 'None'. It is a special value that has its own type:


The functions we have written so far are all void. We will startwriting fruitful functions in a few chapters.


Why functions?[edit]

It may not be clear why it is worth the trouble to dividea program into functions. There are several reasons:

  • Creating a new function gives you an opportunity to name a group of statements, which makes your program easier to read and debug.
  • Functions can make a program smaller by eliminating repetitive code. Later, if you make a change, you only have to make it in one place.
  • Dividing a long program into functions allows you to debug the parts one at a time and then assemble them into a working whole.
  • Well-designed functions are often useful for many programs. Once you write and debug one, you can reuse it.

Debugging[edit]

If you are using a text editor to write your scripts, you mightrun into problems with spaces and tabs. The best way to avoidthese problems is to use spaces exclusively (no tabs). Most texteditors that know about Python do this by default, but somedon't.


Tabs and spaces are usually invisible, which makes themhard to debug, so try to find an editor that manages indentationfor you.


Also, don't forget to save your program before you run it. Somedevelopment environments do this automatically, but some don't.In that case the program you are looking at in the text editoris not the same as the program you are running.


Debugging can take a long time if you keep running the same,incorrect, program over and over!


Make sure that the code you are looking at is the code you are running.If you're not sure, put something like print 'hello' at thebeginning of the program and run it again. If you don't seehello, you're not running the right program!


Glossary[edit]

  • function: A named sequence of statements that performs some

useful operation. Functions may or may not take arguments and may ormay not produce a result.

  • function definition: A statement that creates a new function,

specifying its name, parameters, and the statements it executes.

  • function object: A value created by a function definition.

The name of the function is a variable that refers to a functionobject.

  • header: The first line of a function definition.
  • body: The sequence of statements inside a function definition.
  • parameter: A name used inside a function to refer to the value

passed as an argument.

  • function call: A statement that executes a function. It

consists of the function name followed by an argument list.

  • argument: A value provided to a function when the function is called.

This value is assigned to the corresponding parameter in the function.

  • local variable: A variable defined inside a function. A local

variable can only be used inside its function.

  • return value: The result of a function. If a function call

is used as an expression, the return value is the value ofthe expression.

  • fruitful function: A function that returns a value.
  • void function: A function that doesn't return a value.
  • module: A file that contains a

collection of related functions and other definitions.

  • import statement: A statement that reads a module file and creates

a module object.

  • module object: A value created by an import statement

that provides access to the values defined in a module.

  • dot notation: The syntax for calling a function in another

module by specifying the module name followed by a dot (period) andthe function name.

  • composition: Using an expression as part of a larger expression,

or a statement as part of a larger statement.

  • flow of execution: The order in which statements are executed during

a program run.

  • stack diagram: A graphical representation of a stack of functions,

their variables, and the values they refer to.

  • frame: A box in a stack diagram that represents a function call.

It contains the local variables and parameters of the function.

  • traceback: A list of the functions that are executing,

printed when an exception occurs.

Exercises[edit]

Exercise 3[edit]

Python provides a built-in function called len thatreturns the length of a string, so the value of len('allen') is 5.

Write a function named right_justify that takes a stringnamed s as a parameter and prints the string with enoughleading spaces so that the last letter of the string is in column 70of the display.

Exercise 4[edit]

A function object is a value you can assign to a variableor pass as an argument. For example, do_twice is a functionthat takes a function object as an argument and calls it twice:


Here’s an example that uses do_twice to call a functionnamed print_spam twice.


  1. Type this example into a script and test it.
  2. Modify do_twice so that it takes two arguments, a function object and a value, and calls the function twice, passing the value as an argument.
  3. Write a more general version of print_spam, called print_twice, that takes a string as a parameter and prints it twice.
  4. Use the modified version of do_twice to call print_twice twice, passing 'spam' as an argument.
  5. Define a new function called do_four that takes a function object and a value and calls the function four times, passing the value as a parameter. There should be only two statements in the body of this function, not four.

You can see my solution at thinkpython.com/code/do_four.py.

Exercise 5[edit]

This exercise' can bedone using only the statements and other features we have learned sofar.

  1. Write a function that draws a grid like the following:

Hint: to print more than one value on a line, you can print a comma-separated sequence:

If the sequence ends with a comma, Python leaves the line unfinished, so the value printed next appears on the same line.

The output of these statements is '+ -'.A print statement all by itself ends the current line and goes to the next line.

  1. Use the previous function to draw a similar grid with four rows and four columns.

You can see my solution at thinkpython.com/code/grid.py.

We will see exceptions to this rulelater.Based on an exercise in Oualline, Practical C Programming, Third Edition, O’Reilly (1997)

A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

TurtleWorld[edit]

To accompany this book, I have written a suite of modules called Swampy. One of these modules is TurtleWorld, which provides a set of functions for drawing lines by steering turtles around the screen.

You can download Swampy from thinkpython.com/swampy; follow the instructions there to install Swampy on your system.

Move into the directory that contains TurtleWorld.py, create a file named polygon.py and type in the following code:

The first line is a variation of the import statement we saw before;instead of creating a module object, it imports the functionsfrom the module directly, so you can access them without using dotnotation.

The next lines create a TurtleWorld assigned to world anda Turtle assigned to bob. Printing bob yields somethinglike:

This means that bob refers to an instance of a Turtle as defined in module TurtleWorld. In this context, 'instance' means a member of a set; this Turtle is one of the set of possible Turtles.

wait_for_user tells TurtleWorld to wait for the userto do something, although in this case there's not much forthe user to do except close the window.

TurtleWorld provides severalturtle-steering functions: fd and bk forforward and backward, and lt and rt for left andright turns. Also, each Turtle is holding a pen, which iseither down or up; if the pen is down, the Turtle leavesa trail when it moves. The functions pu and pdstand for “pen up” and “pen down.”

To draw a right angle, add these lines to the program(after creating bob and before calling wait_for_user):

The first line tells bob to take 100 stepsforward. The second line tells him to turn right.

When you run this program, you should see bob move east and thensouth, leaving two line segments behind.

Now modify the program to draw a square. Don’t turn the page untilyou've got it working!

Simple repetition[edit]

Chances are you wrote something like this (leaving out the codethat creates TurtleWorld and waits for the user):

We can do the same thing more concisely with a for statement.Add this example to polygon.py and run it again:



You should see something like this:

This is the simplest use of the for statement; we will seemore later. But that should be enough to let you rewrite yoursquare-drawing program. Don’t turn the page until you do.

Here is a for statement that draws a square:

The syntax of a for statement is similar to a functiondefinition. It has a header that ends with a colon and an indentedbody. The body can contain any number of statements.

A for statement is sometimes called a loop becausethe flow of execution runs through the body and then loops backto the top. In this case, it runs the body four times.

This version is actually a little different from the previoussquare-drawing code because it makes another left turn afterdrawing the last side of the square. The extra turn takes a littlemore time, but it simplifies the code if we do the same thingevery time through the loop. This version also has the effectof leaving the turtle back in the starting position, facing inthe starting direction.

Exercises[edit]

The following is a series of exercises using TurtleWorld. Theyare meant to be fun, but they have a point, too. While you areworking on them, think about what the point is.

The following sections have solutions to the exercises, sodon’t look until you have finished (or at least tried).

  • Write a function called square that takes a parameter

named t, which is a turtle. It should use the turtle to drawa square.Write a function call that passes bob as an argument tosquare, and then run the program again.

  • Add another parameter, named length, to square.

Modify the body so length of the sides is length, and thenmodify the function call to provide a second argument. Run theprogram again. Test your program with a range of values for length.

  • The functions lt and rt make 90-degree turns by

default, but you can provide a second argument that specifies thenumber of degrees. For example, lt(bob, 45) turns bob 45degrees to the left.Make a copy of square and change the name to polygon. Addanother parameter named n and modify the body so it draws ann-sided regular polygon. Hint: The angles of an n-sided regularpolygon are 360.0 / n degrees.



  • Write a function called circle that takes a turtle, t,

and radius, r, as parameters and that draws an approximate circleby invoking polygon with an appropriate length and number ofsides. Test your function with a range of values of r.


Hint: figure out the circumference of the circle and make sure thatlength * n = circumference.

Another hint: if bob is too slow for you, you can speedhim up by changing bob.delay, which is the time between moves,in seconds. bob.delay = 0.01 ought to get him moving.

  • Make a more general version of circle called arc

that takes an additional parameter angle, which determineswhat fraction of a circle to draw. angle is in units ofdegrees, so when angle=360, arc should draw a completecircle.

Encapsulation[edit]

The first exercise asks you to put your square-drawing codeinto a function definition and then call the function, passingthe turtle as a parameter. Here is a solution:

The innermost statements, fd and lt areindented twice to show that they are inside the for loop,which is inside the function definition. The next line,square(bob), is flush with the left margin, so that is theend of both the for loop and the function definition.

Inside the function, t refers to the same turtle bobrefers to, so lt(t) has the same effect as lt(bob).So why not call the parameter bob? The idea is that tcan be any turtle, not just bob, so you could createa second turtle and pass it as an argument to square:

Wrapping a piece of code up in a function is called encapsulation. One of the benefits of encapsulation is that itattaches a name to the code, which serves as a kind of documentation.Another advantage is that if you re-use the code, it is more conciseto call a function twice than to copy and paste the body!

Generalization[edit]

The next step is to add a length parameter to square.Here is a solution:

Adding a parameter to a function is called generalizationbecause it makes the function more general: in the previousversion, the square is always the same size; in this versionit can be any size.

The next step is also a generalization. Instead of drawingsquares, polygon draws regular polygons with any number ofsides. Here is a solution:

This draws a 7-sided polygon with side length 70. If you havemore than a few numeric arguments, it is easy to forget what theyare, or what order they should be in. It is legal, and sometimeshelpful, to include the names of the parameters in the argumentlist:

These are called keyword arguments because they includethe parameter names as “keywords” (not to be confused withPython keywords like while and def).

This syntax makes the program more readable. It is also a reminderabout how arguments and parameters work: when you call a function, thearguments are assigned to the parameters.

Interface design[edit]

The next step is to write circle, which takes a radius,r, as a parameter. Here is a simple solution that usespolygon to draw a 50-sided polygon:

The first line computes the circumference of a circle with radiusr using the formula 2 π r. Since we use math.pi, wehave to import math. By convention, import statementsare usually at the beginning of the script.

n is the number of line segments in our approximation of a circle,so length is the length of each segment. Thus, polygondraws a 50-sides polygon that approximates a circle with radius r.

One limitation of this solution is that n is a constant, whichmeans that for very big circles, the line segments are too long, andfor small circles, we waste time drawing very small segments. Onesolution would be to generalize the function by taking n asa parameter. This would give the user (whoever calls circle)more control, but the interface would be less clean.

The interface of a function is a summary of how it is used: whatare the parameters? What does the function do? And what is the returnvalue? An interface is “clean” if it is “as simple aspossible, but not simpler. (Einstein)”

In this example, r belongs in the interface because itspecifies the circle to be drawn. n is less appropriatebecause it pertains to the details of how the circle shouldbe rendered.

Rather than clutter up the interface, it is betterto choose an appropriate value of ndepending on circumference:

Now the number of segments is (approximately) circumference/3,so the length of each segment is (approximately) 3, which is smallenough that the circles look good, but big enough to be efficient,and appropriate for any size circle.

Refactoring[edit]

When I wrote circle, I was able to re-use polygonbecause a many-sided polygon is a good approximation of a circle.But arc is not as cooperative; we can’t use polygonor circle to draw an arc.

One alternative is to start with a copyof polygon and transform it into arc. The resultmight look like this:

The second half of this function looks like polygon, but wecan’t re-use polygon without changing the interface. We couldgeneralize polygon to take an angle as a third argument,but then polygon would no longer be an appropriate name!Instead, let’s call the more general function polyline:

Now we can rewrite polygon and arc to use polyline:

Finally, we can rewrite circle to use arc:

This process—rearranging a program to improve functioninterfaces and facilitate code re-use—is called refactoring.In this case, we noticed that there was similar code in arc andpolygon, so we “factored it out” into polyline.

If we had planned ahead, we might have written polyline firstand avoided refactoring, but often you don’t know enough at thebeginning of a project to design all the interfaces. Once you startcoding, you understand the problem better. Sometimes refactoring is asign that you have learned something.

A development plan[edit]

A development plan is a process for writing programs.The process we usedin this case study is “encapsulation andgeneralization.” The steps of this process are:

  • Start by writing a small program with no function definitions.
  • Once you get the program working, encapsulate it in a function

and give it a name.

  • Generalize the function by adding appropriate parameters.
  • Repeat steps 1–3 until you have a set of working functions.

Copy and paste working code to avoid retyping (and re-debugging).

  • Look for opportunities to improve the program by refactoring.

For example, if you have similar code in several places, considerfactoring it into an appropriately general function.

This process has some drawbacks—we will see alternatives later—butit can be useful if you don’t know ahead of time how to divide theprogram into functions. This approach lets you design as you goalong.

docstring[edit]

A docstring is a string at the beginning of a function thatexplains the interface (“doc” is short for “documentation”). Hereis an example:

This docstring is a triple-quoted string, also knownas a multiline string because the triple quotes allow the stringto span more than one line.

It is terse, but it contains the essential informationsomeone would need to use this function. It explains concisely whatthe function does (without getting into the details of how it doesit). It explains what effect each parameter has on the behavior ofthe function and what type each parameter should be (if it is notobvious).

Writing this kind of documentation is an important part of interfacedesign. A well-designed interface should be simple to explain;if you are having a hard time explaining one of your functions,that might be a sign that the interface could be improved.

Debugging[edit]

An interface is like a contract between a function and a caller.The caller agrees to provide certain parameters and the functionagrees to do certain work.

For example, polyline requires four arguments. The firsthas to be a Turtle (or some other object that works with fdand lt). The second has to be a number, and it shouldprobably be positive, although it turns out that the functionworks even if it isn’t. The third argument should be an integer;range complains otherwise (depending on which versionof Python you are running). The fourth has to be a number,which is understood to be in degrees.

These requirements are called preconditions because theyare supposed to be true before the function starts executing.Conversely, conditions at the end of the function arepostconditions. Postconditions include the intendedeffect of the function (like drawing line segments) and anyside effects (like moving the Turtle or making other changesin the World).

Preconditions are the responsibility of the caller. If the callerviolates a (properly documented!) precondition and the functiondoesn’t work correctly, the bug is in the caller, not the function.However, for purposes of debugging it is often a good idea forfunctions to check their preconditions rather than assume they aretrue. If every function checks its preconditions before starting,then if something goes wrong, you will know which function to blame.

Glossary[edit]

instance:
A member of a set. The TurtleWorld in thischapter is a member of the set of TurtleWorlds.
loop:
A part of a program that can execute repeatedly.
encapsulation:
The process of transforming a sequence ofstatements into a function definition.
generalization:
The process of replacing somethingunnecessarily specific (like a number) with something appropriatelygeneral (like a variable or parameter).
keyword argument:
An argument that includes the name ofthe parameter as a “keyword.”
interface:
A description of how to use a function, includingthe name and descriptions of the arguments and return value.
development plan:
A process for writing programs.
docstring:
A string that appears in a function definitionto document the function’s interface.
precondition:
A requirement that should be satisfied bythe caller before a function starts.
postcondition:
A requirement that should be satisfied bythe function before it ends.

Exercises[edit]

Exercise 1Download the code in this chapter from'thinkpython.com/code/polygon.py'.

  • Write appropriate docstrings for 'polygon', 'arc' and

'circle'.

  • Draw a stack diagram that shows the state of the program

while executing 'circle(bob, radius)'. You can do thearithmetic by hand or add 'print' statements to the code.

  • The version of 'arc' in Section '4.7' is not

very accurate because the linear approximation of thecircle is always outside the true circle. As a result,the turtle ends up a few units away from the correctdestination. My solution shows a way to reducethe effect of this error. Read the code and see if it makessense to you. If you draw a diagram, you might see how it works.

Exercise 2Write an appropriately general set of functions thatcan draw flowers like this:

You can download a solution from 'thinkpython.com/code/flower.py'.

Exercise 3Write an appropriately general set of functions thatcan draw shapes like this:

<IMG SRC='book006.png'>

You can download a solution from 'thinkpython.com/code/pie.py'.

Exercise 4

'The letters of the alphabet can be constructed from a moderatenumber of basic elements, like vertical and horizontal linesand a few curves. Design a font that can be drawn with aminimal number of basic elements and then write functionsthat draw letters of the alphabet.

You should write one function for each letter, with namesdraw_a, draw_b, etc., and put your functionsin a file named 'letters.py'. You can download a“turtle typewriter” from 'thinkpython.com/code/typewriter.py'to help you test your code.

You can download a solution from 'thinkpython.com/code/letters.py'.

A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Modulus operator[edit]

The modulus operator works on integers and yields the remainderwhen the first operand is divided by the second. In Python, themodulus operator is a percent sign (%). The syntax is the sameas for other operators:

So 7 divided by 3 is 2 with 1 left over.

The modulus operator turns out to be surprisingly useful. Forexample, you can check whether one number is divisible by another—ifx % y is zero, then x is divisible by y.

Also, you can extract the right-most digitor digits from a number. For example, x % 10 yields theright-most digit of x (in base 10). Similarly x % 100yields the last two digits.

Boolean expressions[edit]

A boolean expression is an expression that is either trueor false. The following examples use the operator , which compares two operands and producesTrue if they are equal and False otherwise:

True and False are specialvalues that belong to the type bool; they are not strings:

The operator is one of the comparison operators; theothers are:

Although these operations are probably familiar to you, the Pythonsymbols are different from the mathematical symbols. A common erroris to use a single equal sign (=) instead of a double equal sign(). Remember that = is an assignment operator and is a comparison operator. There is no such thing as=< or =>.

Logical operators[edit]

There are three logical operators: and, or, and not. The semantics (meaning) of these operators issimilar to their meaning in English. For example,x > 0 and x < 10 is true only if x is greater than 0and less than 10.

n%2 0 or n%3 0 is true if either of the conditionsis true, that is, if the number is divisible by 2 or 3.

Finally, the not operator negates a booleanexpression, so not (x > y) is true if x > y is false,that is, if x is less than or equal to y.

Strictly speaking, the operands of the logical operators should beboolean expressions, but Python is not very strict.Any nonzero number is interpreted as “true.”

This flexibility can be useful, but there are some subtleties toit that might be confusing. You might want to avoid it (unlessyou know what you are doing).

Conditional execution[edit]

In order to write useful programs, we almost always need the abilityto check conditions and change the behavior of the programaccordingly. Conditional statements give us this ability. Thesimplest form is the if statement:

The boolean expression after the if statement iscalled the condition. If it is true, then the indentedstatement gets executed. If not, nothing happens.

if statements have the same structure as function definitions:a header followed by an indented block. Statements like this arecalled compound statements.

There is no limit on the number of statements that can appear inthe body, but there has to be at least one.Occasionally, it is useful to have a body with no statements (usuallyas a place keeper for code you haven't written yet). In thatcase, you can use the pass statement, which does nothing.

Alternative execution[edit]

A second form of the if statement is alternative execution,in which there are two possibilities and the condition determineswhich one gets executed. The syntax looks like this:

If the remainder when x is divided by 2 is 0, then weknow that x is even, and the program displays a message to thateffect. If the condition is false, the second set of statements isexecuted. Since the condition must be true or false, exactly one ofthe alternatives will be executed. The alternatives are calledbranches, because they are branches in the flow of execution.

Chained conditionals[edit]

Sometimes there are more than two possibilities and we need more thantwo branches. One way to express a computation like that is a chained conditional:

elif is an abbreviation of “else if.” Again, exactly onebranch will be executed. There is no limit on the number of elif statements. If there is an else clause, it has to beat the end, but there doesn’t have to be one.

Each condition is checked in order. If the first is false,the next is checked, and so on. If one of them istrue, the corresponding branch executes, and the statementends. Even if more than one condition is true, only thefirst true branch executes.

Nested conditionals[edit]

One conditional can also be nested within another. We could havewritten the trichotomy example like this:

The outer conditional contains two branches. Thefirst branch contains a simple statement. The second branchcontains another if statement, which has two branches of itsown. Those two branches are both simple statements,although they could have been conditional statements as well.

Although the indentation of the statements makes the structureapparent, nested conditionals become difficult to read veryquickly. In general, it is a good idea to avoid them when you can.

Logical operators often provide a way to simplify nested conditionalstatements. For example, we can rewrite the following code using asingle conditional:

The print statement is executed only if we make it past bothconditionals, so we can get the same effect with the and operator:

Recursion[edit]

It is legal for one function to call another;it is also legal for a function to call itself. It may not be obviouswhy that is a good thing, but it turns out to be one of the mostmagical things a program can do.For example, look at the following function:

If n is 0 or negative, it outputs the word, “Blastoff!”Otherwise, it outputs n and then calls a function named countdown—itself—passing n-1 as an argument.

What happens if we call this function like this?

The execution of countdown begins with n=3, and sincen is greater than 0, it outputs the value 3, and then calls itself...

The execution of countdown begins with n=2, and since

n is greater than 0, it outputs the value 2, and then calls itself...

The execution of countdown begins with n=1, and since

n is greater than 0, it outputs the value 1, and then calls itself...

The execution of countdown begins with n=0, and since n is not greater than 0, it outputs the word, “Blastoff!” and thenreturns.

The countdown that got n=1 returns.

The countdown that got n=2 returns.

The countdown that got n=3 returns.

And then you’re back in __main__. So, thetotal output looks like this:

A function that calls itself is recursive; the process iscalled recursion.

As another example, we can write a function that prints astring n times.

If n <= 0 the return statement exits the function. Theflow of execution immediately returns to the caller, and the remaininglines of the function are not executed.

The rest of the function is similar to countdown: if n isgreater than 0, it displays s and then calls itself to displaysn−1 additional times. So the number of lines of outputis 1 + (n - 1), which adds up ton.

For simple examples like this, it is probably easier to use a for loop. But we will see examples later that are hard to writewith a for loop and easy to write with recursion, so it isgood to start early.

Stack diagrams for recursive functions[edit]

In Section 3.10, we used a stack diagram to representthe state of a program during a function call. The same kind ofdiagram can help interpret a recursive function.

Every time a function gets called, Python creates a new functionframe, which contains the function’s local variables and parameters.For a recursive function, there might be more than one frame on thestack at the same time.

This figure shows a stack diagram for countdown called withn = 3:

<IMG SRC='book007.png'>

As usual, the top of the stack is the frame for __main__.It is empty because we did not create any variables in __main__ or pass any arguments to it.

The four countdown frames have different values for theparameter n. The bottom of the stack, where n=0, iscalled the base case. It does not make a recursive call, sothere are no more frames.

Draw a stack diagram for print_n called withs = 'Hello' and n=2.

Beginning Your Exercise Program By Math

Write a function called do_n that takes a functionobject and a number, n as arguments, and that callsthe given function n times.

Program

Infinite recursion[edit]

If a recursion never reaches a base case, it goes on makingrecursive calls forever, and the program never terminates. This isknown as infinite recursion, and it is generally nota good idea. Here is a minimal program with an infinite recursion:

In most programming environments, a program with infinite recursiondoes not really run forever. Python reports an errormessage when the maximum recursion depth is reached:

This traceback is a little bigger than the one we saw in theprevious chapter. When the error occurs, there are 1000recurse frames on the stack!

Keyboard input[edit]

The programs we have written so far are a bit rude in the sense thatthey accept no input from the user. They just do the same thing everytime.

Python provides a built-in function called raw_input that getsinput from the keyboard[1]. When this function is called, the program stops andwaits for the user to type something. When the user presses Return or Enter, the program resumes and raw_inputreturns what the user typed as a string.

Before getting input from the user, it is a good idea to print aprompt telling the user what to input. raw_input can take aprompt as an argument:

The sequence n at the end of the prompt represents a newline,which is a special character that causes a line break.That’s why the user’s input appears below the prompt.

If you expect the user to type an integer, you can try to convertthe return value to int:

But if the user types something other than a string of digits,you get an error:

We will see how to handle this kind of error later.

Debugging[edit]

The traceback Python displays when an error occurs containsa lot of information, but it can be overwhelming, especiallywhen there are many frames on the stack. The mostuseful parts are usually:

  • What kind of error it was, and
  • Where it occurred.

Syntax errors are usually easy to find, but there are a fewgotchas. Whitespace errors can be tricky because spaces andtabs are invisible and we are used to ignoring them.

In this example, the problem is that the second line is indented byone space. But the error message points to y, which ismisleading. In general, error messages indicate where the problem wasdiscovered, but the actual error might be earlier in the code,sometimes on a previous line.

The same is true of runtime errors. Suppose you are tryingto compute a signal-to-noise ratio in decibels. The formulais SNRdb = 10 log10 (Psignal / Pnoise). In Python,you might write something like this:

But when you run it, you get an error message:

The error message indicates line 5, but there is nothingwrong with that line. To find the real error, it might beuseful to print the value of ratio, which turns out tobe 0. The problem is in line 4, because dividing two integersdoes floor division. The solution is to represent signal powerand noise power with floating-point values.

In general, error messages tell you where the problem was discovered, but that is often not where it was caused.

Books Never Written Math Beginning Your Exercise Program By Walking One Mile

Glossary[edit]

modulus operator:
An operator, denoted with a percent sign(%), that works on integers and yields the remainder when onenumber is divided by another.
boolean expression:
An expression whose value is either True or False.
comparison operator:
One of the operators that comparesits operands: , !=, >, <, >=, and <=.
logical operator:
One of the operators that combines booleanexpressions: and, or, and not.
conditional statement:
A statement that controls the flow ofexecution depending on some condition.
condition:
The boolean expression in a conditional statementthat determines which branch is executed.
compound statement:
A statement that consists of a headerand a body. The header ends with a colon (:). The body is indentedrelative to the header.
body:
The sequence of statements within a compound statement.
branch:
One of the alternative sequences of statements ina conditional statement.
chained conditional:
A conditional statement with a seriesof alternative branches.
nested conditional:
A conditional statement that appearsin one of the branches of another conditional statement.
recursion:
The process of calling the function that iscurrently executing.
base case:
A conditional branch in arecursive function that does not make a recursive call.
infinite recursion:
A function that calls itself recursivelywithout ever reaching the base case. Eventually, an infinite recursioncauses a runtime error.

Exercises[edit]

Exercise 1Fermat’s Last Theorem says that there are no integers'a', 'b', and 'c' such that

an + bn = cn

for any values of 'n' greater than 2.

  • Write a function named check_fermat that takes four

parameters—'a', 'b', 'c' and 'n'—andthat checks to see if Fermat’s theorem holds. If

'n' is greater than 2 and it turns out to be true that
'a''n'' + b''n'' = c''n'' '

'the program should print, “Holy smokes, Fermat was wrong!”Otherwise the program should print, “No, that doesn’t work.”'

  • 'Write a function that prompts the user to input values

for ''a'', ''b'', ''c'' and ''n'', converts them tointegers, and uses ''check_fermat'' to check whether theyviolate Fermat’s theorem.'

Exercise 2If you are given three sticks, you may or may not be able to arrangethem in a triangle. For example, if one of the sticks is 12 incheslong and the other two are one inch long, it is clear that you willnot be able to get the short sticks to meet in the middle. For anythree lengths, there is a simple test to see if it is possible to forma triangle:

“If any of the three lengths is greater than the sum of the othertwo, then you cannot form a triangle. Otherwise, youcan[2].”

  • Write a function named is_triangle that takes three

integers as arguments, and that prints either “Yes” or “No,” dependingon whether you can or cannot form a triangle from sticks with thegiven lengths.

  • Write a function that prompts the user to input three stick

lengths, converts them to integers, and uses is_triangle tocheck whether sticks with the given lengths can form a triangle.

The following exercises use TurtleWorld from Chapter 4:

Exercise 3Read the following function and see if you can figure outwhat it does. Then run it (see the examples in Chapter '4').

Exercise 4

The Koch curve is a fractal that looks something likethis:

To draw a Koch curve with length 'x', all you have to do is

  • Draw a Koch curve with length 'x/3'.
  • Turn left 60 degrees.
  • Draw a Koch curve with length 'x/3'.
  • Turn right 120 degrees.
  • Draw a Koch curve with length 'x/3'.
  • Turn left 60 degrees.
  • Draw a Koch curve with length 'x/3'.

The only exception is if 'x' is less than 3. In that case,you can just draw a straight line with length 'x'.

  • Write a function called 'koch' that takes a turtle and

a length as parameters, and that uses the turtle to draw a Kochcurve with the given length.

  • Write a function called 'snowflake' that draws three

Koch curves to make the outline of a snowflake.You can see my solution at 'thinkpython.com/code/koch.py'.

  • The Koch curve can be generalized in several ways. See

'wikipedia.org/wiki/Koch_snowflake' for examples andimplement your favorite.

Notes[edit]

  1. In Python 3.0, this function is named input
  2. If the sum of two lengths equals the third, they formwhat is called a “degenerate” triangle.

Return values[edit]

Some of the built-in functions we have used, such as the mathfunctions, produce results. Calling the function generates avalue, which we usually assign to a variable or use as part of anexpression.

All of the functions we have written so far are void; they printsomething or move turtles around, but their return value is None.

In this chapter, we are (finally) going to write fruitful functions.The first example is area, which returns the area of a circlewith the given radius:

We have seen the return statement before, but in a fruitfulfunction the return statement includesan expression. This statement means: “Return immediately fromthis function and use the following expression as a return value.”The expression can be arbitrarily complicated, so we couldhave written this function more concisely:

On the other hand, temporary variables like temp often makedebugging easier.

Sometimes it is useful to have multiple return statements, one in eachbranch of a conditional:

Since these return statements are in an alternative conditional,only one will be executed.

As soon as a return statement executes, the functionterminates without executing any subsequent statements.Code that appears after a return statement, or any other placethe flow of execution can never reach, is called dead code.

In a fruitful function, it is a good idea to ensurethat every possible path through the program hits areturn statement. For example:

This function is incorrect because if x happens to be 0,neither condition is true, and the function ends without hitting areturn statement. If the flow of execution gets to the endof a function, the return value is None, which is notthe absolute value of 0.

By the way, Python provides a built-in function called abs that computes absolute values.

Exercise 1[edit]

Write a 'compare' functionthat returns '1' if 'x > y','0' if 'x y', and '-1' if 'x < y'.

Incremental development[edit]

As you write larger functions, you might find yourselfspending more time debugging.

To deal with increasingly complex programs,you might want to try a process calledincremental development. The goal of incremental developmentis to avoid long debugging sessions by adding and testing onlya small amount of code at a time.

As an example, suppose you want to find the distance between twopoints, given by the coordinates (x1, y1) and (x2, y2).By the Pythagorean theorem, the distance is:

distance=(x2x1)2+(y2y1)2{displaystyle {text{distance}}={sqrt {(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}}}}

The first step is to consider what a distance function shouldlook like in Python. In other words, what are the inputs (parameters)and what is the output (return value)?

In this case, the inputs are two points, which you can representusing four numbers. The return value is the distance, which isa floating-point value.

Already you can write an outline of the function:

Obviously, this version doesn't compute distances; it always returnszero. But it is syntactically correct, and it runs, which means thatyou can test it before you make it more complicated.

To test the new function, call it with sample arguments:

I chose these values so that the horizontal distance is 3 and thevertical distance is 4; that way, the result is 5(the hypotenuse of a 3-4-5 triangle). When testing a function, it isuseful to know the right answer.

At this point we have confirmed that the function is syntacticallycorrect, and we can start adding code to the body.A reasonable next step is to find the differencesx2x1 and y2y1. The next version stores those values intemporary variables and prints them.

If the function is working, it should display 'dx is 3' and ’dy is 4’. If so, we know that the function is getting the rightarguments and performing the first computation correctly. If not,there are only a few lines to check.

Next we compute the sum of squares of dx and dy:

Again, you would run the program at this stage and check the output(which should be 25).Finally, you can use math.sqrt to compute and return the result:

If that works correctly, you are done. Otherwise, you mightwant to print the value of result before the returnstatement.

The final version of the function doesn’t display anything when itruns; it only returns a value. The print statements we wroteare useful for debugging, but once you get the function working, youshould remove them. Code like that is called scaffoldingbecause it is helpful for building the program but is not part of thefinal product.

When you start out, you should add only a line or two of code at atime. As you gain more experience, you might find yourself writingand debugging bigger chunks. Either way, incremental developmentcan save you a lot of debugging time.

The key aspects of the process are:

  • Start with a working program and make small incremental changes. At any point, if there is an error, you should have a good idea where it is.
  • Use temporary variables to hold intermediate values so you can display and check them.
  • Once the program is working, you might want to remove some of the scaffolding or consolidate multiple statements into compound expressions, but only if it does not make the program difficult to read.

Exercise 2[edit]

Use incremental development to write a functioncalled 'hypotenuse' that returns the length of the hypotenuse of aright triangle given the lengths of the two legs as arguments.Record each stage of the development process as you go.

Composition[edit]

As you should expect by now, you can call one function fromwithin another. This ability is called composition.

As an example, we’ll write a function that takes two points,the center of the circle and a point on the perimeter, and computesthe area of the circle.

Assume that the center point is stored in the variables xc andyc, and the perimeter point is in xp and yp. Thefirst step is to find the radius of the circle, which is the distancebetween the two points. We just wrote a function, distance, that does that:

The next step is to find the area of a circle with that radius;we just wrote that, too:

Encapsulating these steps in a function, we get:

The temporary variables radius and result are useful fordevelopment and debugging, but once the program is working, we canmake it more concise by composing the function calls:

Boolean functions[edit]

Functions can return booleans, which is often convenient for hidingcomplicated tests inside functions. For example:

It is common to give boolean functions names that sound like yes/noquestions; is_divisible returns either True or Falseto indicate whether x is divisible by y.

Here is an example:

The result of the operator is a boolean, so we can write thefunction more concisely by returning it directly:

Boolean functions are often used in conditional statements:

It might be tempting to write something like:

But the extra comparison is unnecessary.

Exercise 3

Write a function is_between(x, y, z) thatreturns 'True' if 'xyz' or 'False' otherwise.

More recursion[edit]

We have only covered a small subset of Python, but you mightbe interested to know that this subset is a completeprogramming language, which means that anything that can becomputed can be expressed in this language. Any program ever writtencould be rewritten using only the language features you have learnedso far (actually, you would need a few commands to control deviceslike the keyboard, mouse, disks, etc., but that’s all).

Proving that claim is a nontrivial exercise first accomplished by AlanTuring, one of the first computer scientists (some would argue that hewas a mathematician, but a lot of early computer scientists started asmathematicians). Accordingly, it is known as the Turing Thesis.For a more complete (and accurate) discussion of the Turing Thesis,I recommend Michael Sipser’s book Introduction to theTheory of Computation.

To give you an idea of what you can do with the tools you have learnedso far, we’ll evaluate a few recursively defined mathematicalfunctions. A recursive definition is similar to a circulardefinition, in the sense that the definition contains a reference tothe thing being defined. A truly circular definition is not veryuseful:

frabjuous:
An adjective used to describe something that is frabjuous.

If you saw that definition in the dictionary, you might be annoyed. Onthe other hand, if you looked up the definition of the factorialfunction, denoted with the symbol !, you might get something likethis:

One more example[edit]

After factorial, the most common example of a recursivelydefined mathematical function is fibonacci, which has thefollowing definition[1]:

None':
A special value returned by functions thathave no return statement or a return statement without an argument.
incremental development:
A program development plan intended toavoid debugging by adding and testing onlya small amount of code at a time.
scaffolding:
Code that is used during program development but isnot part of the final version.
guardian:
A programming pattern that uses a conditionalstatement to check for and handle circumstances thatmight cause an error.

Exercises[edit]

Exercise 4[edit]

Draw a stack diagram for the following program. What does the program print?

Exercise 5[edit]

The Ackermann function, 'A(m, n)' is defined[3]:

A(M,N)={n+1if m=0A(m1,1)if m>0 and n=0A(m1,A(m,n1))if m>0 and n>0{displaystyle A(M,N)={begin{cases}n+1&{mbox{if }}m=0A(m-1,1)&{mbox{if }}m>0{mbox{ and }}n=0A(m-1,A(m,n-1))&{mbox{if }}m>0{mbox{ and }}n>0end{cases}}}

Write a function named 'ack' that evaluates Ackerman’s function.Use your function to evaluate 'ack(3, 4)', which should be 125.What happens for larger values of 'm' and 'n'?

Exercise 6[edit]

A palindrome is a word that is spelled the same backward andforward, like “noon” and “redivider”. Recursively, a wordis a palindrome if the first and last letters are the sameand the middle is a palindrome.

The following are functions that take a string argument andreturn the first, last, and middle letters:

We’ll see how they work in Chapter '8'.

  • Type these functions into a file named 'palindrome.py'

and test them out. What happens if you call 'middle' witha string with two letters? One letter? What about the emptystring, which is written ' and contains no letters?

  • Write a function called is_palindrome that takes

a string argument and returns 'True' if it is a palindromeand 'False' otherwise. Remember that you can use thebuilt-in function 'len' to check the length of a string.

Exercise 7[edit]

A number, 'a', is a power of 'b' if it is divisible by 'b'and 'a/b' is a power of 'b'. Write a function calledis_power that takes parameters 'a' and 'b'and returns 'True' if 'a' is a power of 'b'.

Exercise 8[edit]

The greatest common divisor (GCD) of 'a' and 'b' is the largest numberthat divides both of them with no remainder[4].

One way to find the GCD of two numbers is Euclid’s algorithm,which is based on the observation that if 'r' is the remainderwhen 'a' is divided by 'b', then 'gcd(a, b) = gcd(b, r)'.As a base case, we can consider 'gcd(a, 0) = a'.

Write a function calledgcd that takes parameters 'a' and 'b'and returns their greatest common divisor. If you needhelp, see 'wikipedia.org/wiki/Euclidean_algorithm'.

Notes[edit]

  1. Seewikipedia.org/wiki/Fibonacci_number.
  2. Seewikipedia.org/wiki/Gamma_function.
  3. Seewikipedia.org/wiki/Ackermann_function
  4. This exercise isbased on an example from Abelson and Sussman’s Structure andInterpretation of Computer Programs.

Multiple assignment[edit]

As you may have discovered, it is legal tomake more than one assignment to the same variable. Anew assignment makes an existing variable refer to a newvalue (and stop referring to the old value).

The output of this program is 5 7, because the first time bruce is printed, its value is 5, and the second time, its value is 7. The comma at the end of the first print statement suppresses the newline, which is why both outputs appear on the same line.

Here is what multiple assignment looks like in a state diagram:

With multiple assignment it is especially important to distinguishbetween an assignment operation and a statement of equality. BecausePython uses the equal sign (=) for assignment, it is tempting tointerpret a statement like a = b as a statement of equality. Itis not!

First, equality is a symmetric relation and assignment is not. Forexample, in mathematics, if a = 7 then 7 = a. But in Python, thestatement a = 7 is legal and 7 = a is not.

Furthermore, in mathematics, a statement of equality is either true orfalse, for all time. If a = b now, then a will always equal b.In Python, an assignment statement can make two variables equal, butthey don’t have to stay that way:

The third line changes the value of a but does not change thevalue of b, so they are no longer equal.

Although multiple assignment is frequently helpful, you should use itwith caution. If the values of variables change frequently, it canmake the code difficult to read and debug.

Updating variables[edit]

One of the most common forms of multiple assignment is an update,where the new value of the variable depends on the old.

This means “get the current value of x, add one, and thenupdate x with the new value.”

If you try to update a variable that doesn’t exist, you get anerror, because Python evaluates the right side before it assignsa value to x:

Before you can update a variable, you have to initializeit, usually with a simple assignment:

Updating a variable by adding 1 is called an increment;subtracting 1 is called a decrement.

The while statement[edit]

Computers are often used to automate repetitive tasks. Repeatingidentical or similar tasks without making errors is something thatcomputers do well and people do poorly.

We have seen two programs, countdown and print_n, thatuse recursion to perform repetition, which is also called iteration. Because iteration is so common, Python provides severallanguage features to make it easier. One is the for statementwe saw in Section 4.2. We’ll get back to that later.

Another is the while statement. Here is a version of countdown that uses a while statement:

You can almost read the while statement as if it were English.It means, “While n is greater than 0,display the value of n and then reduce the value ofn by 1. When you get to 0, display the word Blastoff!

More formally, here is the flow of execution for a while statement:

  • Evaluate the condition, yielding True or False.
  • If the condition is false, exit the while statement and continue execution at the next statement.
  • If the condition is true, execute the body and then go back to step 1.

This type of flow is called a loop because the third steploops back around to the top.

The body of the loop should change the value of one or more variablesso that eventually the condition becomes false and the loopterminates. Otherwise the loop will repeat forever, which is calledan infinite loop. An endless source of amusement for computerscientists is the observation that the directions on shampoo,“Lather, rinse, repeat,” are an infinite loop.

In the case of countdown, we can prove that the loopterminates because we know that the value of n is finite, and wecan see that the value of n gets smaller each time through theloop, so eventually we have to get to 0. In othercases, it is not so easy to tell:

The condition for this loop is n != 1, so the loop will continueuntil n is 1, which makes the condition false.

Each time through the loop, the program outputs the value of nand then checks whether it is even or odd. If it is even, n is divided by 2. If it is odd, the value of n is replaced withn*3+1. For example, if the argument passedto sequence is 3, the resulting sequence is 3, 10, 5, 16, 8, 4, 2, 1.

Since n sometimes increases and sometimes decreases, there is noobvious proof that n will ever reach 1, or that the programterminates. For some particular values of n, we can provetermination. For example, if the starting value is a power of two,then the value of n will be even each time through the loopuntil it reaches 1. The previous example ends with such a sequence,starting with 16.

The hard question is whether we can prove that this program terminatesfor all positive values of n. So far1, no one hasbeen able to prove it or disprove it!

Exercise 1

Rewrite the function print_n fromSection '5.8' using iteration instead of recursion.

break[edit]

Sometimes you don’t know it’s time to end a loop until you get halfway through the body. In that case you can use the breakstatement to jump out of the loop.

For example, suppose you want to take input from the user until theytype done. You could write:

The loop condition is True, which is always true, so theloop runs until it hits the break statement.

Each time through, it prompts the user with an angle bracket.If the user types done, the break statement exitsthe loop. Otherwise the program echoes whatever the user typesand goes back to the top of the loop. Here’s a sample run:

This way of writing while loops is common because youcan check the condition anywhere in the loop (not just at thetop) and you can express the stop condition affirmatively(“stop when this happens”) rather than negatively (“keep goinguntil that happens.”).

Square roots[edit]

Loops are often used in programs that computenumerical results by starting with an approximate answer anditeratively improving it.

For example, one way of computing square roots is Newton’s method.Suppose that you want to know the square root of a. If you startwith almost any estimate, x, you can compute a betterestimate with the following formula:

y =
x + a/x
2

For example, if a is 4 and x is 3:

Which is closer to the correct answer (√4 = 2). If werepeat the process with the new estimate, it gets even closer:

After a few more updates, the estimate is almost exact:

In general we don’t know ahead of time how many steps it takesto get to the right answer, but we know when we get therebecause the estimatestops changing:

When y x, we can stop. Here is a loop that startswith an initial estimate, x, and improves it until itstops changing:

For most values of a this works fine, but in general it isdangerous to test float equality.Floating-point values are only approximately right:most rational numbers, like 1/3, and irrational numbers, like√2, can’t be represented exactly with a float.

Rather than checking whether x and y are exactly equal, itis safer to use the built-in function abs to compute theabsolute value, or magnitude, of the difference between them:

Where epsilon has a value like 0.0000001 thatdetermines how close is close enough.

Exercise 2

'Encapsulate this loop in a function called square_rootthat takes 'a' as a parameter, chooses a reasonablevalue of 'x', and returns an estimate of the square rootof 'a'.

Algorithms[edit]

Newton’s method is an example of an algorithm: it is amechanical process for solving a category of problems (in thiscase, computing square roots).

It is not easy to define an algorithm. It might help to startwith something that is not an algorithm. When you learnedto multiply single-digit numbers, you probably memorized themultiplication table. In effect, you memorized 100 specific solutions.That kind of knowledge is not algorithmic.

But if you were “lazy,” you probably cheated by learning a fewtricks. For example, to find the product of n and 9, you canwrite n−1 as the first digit and 10−n as the seconddigit. This trick is a general solution for multiplying anysingle-digit number by 9. That’s an algorithm!

Similarly, the techniques you learned for addition with carrying,subtraction with borrowing, and long division are all algorithms. Oneof the characteristics of algorithms is that they do not require anyintelligence to carry out. They are mechanical processes in whicheach step follows from the last according to a simple set of rules.

In my opinion, it is embarrassing that humans spend so much time inschool learning to execute algorithms that, quite literally, requireno intelligence.

On the other hand, the process of designing algorithms is interesting,intellectually challenging, and a central part of what we callprogramming.

Some of the things that people do naturally, without difficulty orconscious thought, are the hardest to express algorithmically.Understanding natural language is a good example. We all do it, butso far no one has been able to explain how we do it, at leastnot in the form of an algorithm.

Debugging[edit]

As you start writing bigger programs, you might find yourselfspending more time debugging. More code means more chances tomake an error and more place for bugs to hide.

One way to cut your debugging time is “debugging by bisection.”For example, if there are 100 lines in your program and youcheck them one at a time, it would take 100 steps.

Instead, try to break the problem in half. Look at the middleof the program, or near it, for an intermediate value youcan check. Add a print statement (or something elsethat has a verifiable effect) and run the program.

If the mid-point check is incorrect, the problem must be in thefirst half of the program. If it is correct, the problem isin the second half.

Every time you perform a check like this, you halve the numberof lines you have to search. After six steps (which is muchless than 100), you would be down to one or two lines of code,at least in theory.

In practice it is not always clear whatthe “middle of the program” is and not always possible tocheck it. It doesn’t make sense to count lines and find theexact midpoint. Instead, think about placesin the program where there might be errors and places where itis easy to put a check. Then choose a spot where youthink the chances are about the same that the bug is beforeor after the check.

Glossary[edit]

multiple assignment:
Making more than one assignment to the samevariable during the execution of a program.
update:
An assignment where the new value of the variabledepends on the old.
initialize:
An assignment that gives an initial value toa variable that will be updated.
increment:
An update that increases the value of a variable(often by one).
decrement:
An update that decreases the value of a variable.
iteration:
Repeated execution of a set of statements usingeither a recursive function call or a loop.
infinite loop:
A loop in which the terminating condition isnever satisfied.

Exercises[edit]

Exercise 3[edit]

To test the square root algorithm in this chapter, you could compareit with 'math.sqrt'. Write a function named test_square_rootthat prints a table like this:

The first column is a number, 'a'; the second column isthe square root of 'a' computed with the function fromExercise '7.2'; the third column is the square root computedby 'math.sqrt'; the fourth column is the absolute valueof the difference between the two estimates.

Exercise 4[edit]

The built-in function 'eval' takes a string and evaluatesit using the Python interpreter. For example:

Write a function called eval_loop that iterativelyprompts the user, takes the resulting input and evaluatesit using 'eval', and prints the result.

It should continue until the user enters done, and thenreturn the value of the last expression it evaluated.

Exercise 5[edit]

The brilliant mathematician Srinivasa Ramanujan found aninfinite series2that can be used to generate a numericalapproximation of π{displaystyle pi }:

1π=229801k=0(4k)!(1103+26390k)(k!)43964k{displaystyle {frac {1}{pi }}={frac {2{sqrt {2}}}{9801}}sum _{k=0}^{infty }{frac {(4k)!(1103+26390k)}{(k!)^{4}396^{4k}}}}

Write a function called estimate_pi that uses this formulato compute and return an estimate of 'π'. It should use a 'while'loop to compute terms of the summation until the last term issmaller than '1e-15' (which is Python notation for '10−15).You can check the result by comparing it to 'math.pi'.

You can see my solution at 'thinkpython.com/code/pi.py'.

1
Seewikipedia.org/wiki/Collatz_conjecture.
2
See wikipedia.org/wiki/Pi.

A string is a sequence[edit]

A string is a sequence of characters. You can access the characters one at a time with thebracket operator:

The second statement selects character number 1 from fruit and assigns it to letter.

The expression in brackets is called an index. The index indicates which character in the sequence youwant (hence the name).

But you might not get what you expect:

For most people, the first letter of 'banana' is b, nota. But for computer scientists, the index is an offset from thebeginning of the string, and the offset of the first letter is zero.

So b is the 0th letter (“zero-eth”) of 'banana', ais the 1th letter (“one-eth”), and n is the 2th (“two-eth”)letter.

You can use any expression, including variables and operators, as anindex, but the value of the index has to be an integer. Otherwise youget:

len[edit]

len is a built-in function that returns the number of charactersin a string:

To get the last letter of a string, you might be tempted to try somethinglike this:

The reason for the IndexError is that there is no letter in ’banana’ with the index 6. Since we started counting at zero, thesix letters are numbered 0 to 5. To get the last character, you haveto subtract 1 from length:

Alternatively, you can use negative indices, which count backward fromthe end of the string. The expression fruit[-1] yields the lastletter, fruit[-2] yields the second to last, and so on.

Traversal with a for loop[edit]

A lot of computations involve processing a string one character at atime. Often they start at the beginning, select each character inturn, do something to it, and continue until the end. This pattern ofprocessing is called a traversal. One way to write a traversalis with a while loop:

This loop traverses the string and displays each letter on a line byitself. The loop condition is index < len(fruit), sowhen index is equal to the length of the string, thecondition is false, and the body of the loop is not executed. Thelast character accessed is the one with the index len(fruit)-1,which is the last character in the string.

Exercise 1

Write a function that takes a string as an argumentand displays the letters backward, one per line.

Another way to write a traversal is with a for loop:

Each time through the loop, the next character in the string is assignedto the variable char. The loop continues until no characters areleft.

The following example shows how to use concatenation (string addition)and a for loop to generate an abecedarian series (that is, inalphabetical order). In Robert McCloskey’s book MakeWay for Ducklings, the names of the ducklings are Jack, Kack, Lack,Mack, Nack, Ouack, Pack, and Quack. This loop outputs these names inorder:

The output is:

Of course, that’s not quite right because “Ouack” and“Quack” are misspelled.

Exercise 2[edit]

Modify the program to fix this error.

String slices[edit]

A segment of a string is called a slice. Selecting a slice issimilar to selecting a character:

The operator [n:m] returns the part of the string from the “n-eth” character to the “m-eth” character, including the first butexcluding the last. This behavior is counterintuitive, but it mighthelp to imagine the indices pointing between thecharacters, as in the following diagram:

If you omit the first index (before the colon), the slice starts atthe beginning of the string. If you omit the second index, the slicegoes to the end of the string:

If the first index is greater than or equal to the second the resultis an empty string, represented by two quotation marks:

An empty string contains no characters and has length 0, but otherthan that, it is the same as any other string.

Exercise 3[edit]

Given that 'fruit' is a string, what does'fruit[:]' mean?

Strings are immutable[edit]

It is tempting to use the [] operator on the left side of anassignment, with the intention of changing a character in a string.For example:

The “object” in this case is the string and the “item” isthe character you tried to assign. For now, an object isthe same thing as a value, but we will refine that definitionlater. An item is one of the values in a sequence.

The reason for the error is thatstrings are immutable, which means you can’t change anexisting string. The best you can do is create a new stringthat is a variation on the original:

This example concatenates a new first letter ontoa slice of greeting. It has no effect onthe original string.

Searching[edit]

What does the following function do?

In a sense, find is the opposite of the [] operator.Instead of taking an index and extracting the corresponding character,it takes a character and finds the index where that characterappears. If the character is not found, the function returns -1.

This is the first example we have seen of a return statementinside a loop. If word[index] letter, the function breaksout of the loop and returns immediately.

If the character doesn’t appear in the string, the programexits the loop normally and returns -1.

This pattern of computation—traversing a sequence and returningwhen we find what we are looking for—is a called a search.

Exercise 4[edit]

Modify 'find' so that it has athird parameter, the index in 'word' where it should startlooking.

Looping and counting[edit]

The following program counts the number of times the letter aappears in a string:

This program demonstrates another pattern of computation called a counter. The variable count is initialized to 0 and thenincremented each time an a is found.When the loop exits, countcontains the result—the total number of a’s.

Exercise 5

Encapsulate this code in a function named 'count', and generalize it so that it accepts the string and theletter as arguments.

Exercise 6

Rewrite this function so that instead oftraversing the string, it uses the three-parameter version of 'find' from the previous section.

string methods[edit]

A method is similar to a function—it takes arguments andreturns a value—but the syntax is different. For example, themethod upper takes a string and returns a new string withall uppercase letters:

Instead of the function syntax upper(word), it usesthe method syntax word.upper().

This form of dot notation specifies the name of the method, upper, and the name of the string to apply the method to, word. The empty parentheses indicate that this method takes noargument.

A method call is called an invocation; in this case, we wouldsay that we are invoking upper on the word.

As it turns out, there is a string method named find thatis remarkably similar to the function we wrote:

In this example, we invoke find on word and passthe letter we are looking for as a parameter.

Actually, the find method is more general than our function;it can find substrings, not just characters:

It can take as a second argument the index where it should start:


And as a third argument the index where it should stop:

This search fails because b does notappear in the index range from 1 to 2 (not including 2).

Exercise 7

'There is a string method called 'count' that is similarto the function in the previous exercise. Read the documentationof this methodand write an invocation that counts the number of 'a'sin banana.

The in operator[edit]

The word in is a boolean operator that takes two strings andreturns True if the first appears as a substring in the second:

For example, the following function prints all theletters from word1 that also appear in word2:

With well-chosen variable names,Python sometimes reads like English. You could readthis loop, “for (each) letter in (the first) word, if (the) letter (appears) in (the second) word, print (the) letter.”

Here’s what you get if you compare apples and oranges:

String comparison[edit]

The comparison operators work on strings. To see if two strings are equal:

Other comparison operations are useful for putting words in alphabeticalorder:

Python does not handle uppercase and lowercase letters the same waythat people do. All the uppercase letters come before all thelowercase letters, so:

A common way to address this problem is to convert strings to astandard format, such as all lowercase, before performing thecomparison. Keep that in mind in case you have to defend yourselfagainst a man armed with a Pineapple.

Debugging[edit]

When you use indices to traverse the values in a sequence,it is tricky to get the beginning and end of the traversalright. Here is a function that is supposed to compare twowords and return True if one of the words is the reverseof the other, but it contains two errors:

The first if statement checks whether the words are thesame length. If not, we can return False immediatelyand then, for the rest of the function, we can assume that the wordsare the same length. This is an example of the guardian patternin Section 6.8.

i and j are indices: i traverses word1forward while j traverses word2 backward. If we findtwo letters that don’t match, we can return False immediately.If we get through the whole loop and all the letters match, wereturn True.

If we test this function with the words “pots” and “stop”, weexpect the return value True, but we get an IndexError:


For debugging this kind of error, my first move is toprint the values of the indices immediately before the linewhere the error appears.

Now when I run the program again, I get more information:

The first time through the loop, the value of j is 4,which is out of range for the string 'pots'.The index of the last character is 3, so theinitial value for j should be len(word2)-1.



If I fix that error and run the program again, I get:

This time we get the right answer, but it looks like the loop only ranthree times, which is suspicious. To get a better idea of what ishappening, it is useful to draw a state diagram. During the firstiteration, the frame for is_reverse looks like this:


I took a little license by arranging the variables in the frameand adding dotted lines to show that the values of i andj indicate characters in word1 and word2.

Exercise 8

'Starting with this diagram, execute the program on paper, changing thevalues of 'i' and 'j' during each iteration. Find and fix thesecond error in this function.

Glossary[edit]

object:
Something a variable can refer to. For now,you can use “object” and “value” interchangeably.
sequence:
An ordered set; that is, a set ofvalues where each value is identified by an integer index.
item:
One of the values in a sequence.
index:
An integer value used to select an item ina sequence, such as a character in a string.
slice:
A part of a string specified by a range of indices.
empty string:
A string with no characters and length 0, representedby two quotation marks.
immutable:
The property of a sequence whose items cannotbe assigned.
traverse:
To iterate through the items in a sequence,performing a similar operation on each.
search:
A pattern of traversal that stopswhen it finds what it is looking for.
counter:
A variable used to count something, usually initializedto zero and then incremented.
method:
A function that is associated with an object and calledusing dot notation.
invocation:
A statement that calls a method.

Exercises[edit]

Exercise 9[edit]

A string slice can take a third index that specifies the “stepsize;” that is, the number of spaces between successive characters.A step size of 2 means every other character; 3 means every third,etc.

A step size of -1 goes through the word backwards, sothe slice [::-1] generates a reversed string.

Use this idiom to write a one-line version of is_palindromefrom Exercise '6.6'.

Exercise 10[edit]

Read the documentation of the string methods at'docs.python.org/lib/string-methods.html'. Youmight want to experiment with some of them to make sureyou understand how they work. 'strip' and'replace' are particularly useful.

The documentation uses a syntax that might be confusing.For example, in find(sub[, start[, end]]), the bracketsindicate optional arguments. So 'sub' is required, but'start' is optional, and if you include 'start',then 'end' is optional.

Exercise 11[edit]

The following functions are all intended to check whether astring contains any lowercase letters, but at least some of them are

wrong. For each function, describe what the function actually does.

Exercise 12[edit]

ROT13 is a weak form of encryption that involves “rotating” eachletter in a word by 13 places[1]. To rotate a letter meansto shift it through the alphabet, wrapping around to the beginning ifnecessary, so ’A’ shifted by 3 is ’D’ and ’Z’ shifted by 1 is ’A’.

Write a function called rotate_wordthat takes a string and an integer as parameters, and that returnsa new string that contains the letters from the original string“rotated” by the given amount.

For example, “cheer” rotated by 7 is “jolly” and “melon” rotatedby -10 is “cubed”.

You might want to use the built-in functions 'ord', which convertsa character to a numeric code, and 'chr', which converts numericcodes to characters.

Potentially offensive jokes on the Internet are sometimes encodedin ROT13. If you are not easily offended, find and decode someof them.

Notes[edit]

Reading word lists[edit]

For the exercises in this chapter we need a list of English words.There are lots of word lists available on the Web, but the one mostsuitable for our purpose is one of the word lists collected andcontributed to the public domain by Grady Ward as part of the Mobylexicon project[1]. Itis a list of 113,809 official crosswords; that is, words that areconsidered valid in crossword puzzles and other word games. In theMoby collection, the filename is 113809of.fic; I include a copyof this file, with the simpler name words.txt, along withSwampy.

This file is in plain text, so you can open it with a texteditor, but you can also read it from Python. (You may need to move the file from the swampy folder into the main python folder) The built-infunction open takes the name of the file as a parameterand returns a file object you can use to read the file.

fin is a common name for a file object used forinput. Mode 'r' indicates that this file is open forreading (as opposed to 'w' for writing).

The file object provides several methods for reading, includingreadline, which reads characters from the fileuntil it gets to a newline and returns the result as astring:

The first word in this particular list is “aa,” which is a kind oflava. The sequence rn represents two whitespace characters,a carriage return and a newline, that separate this word from thenext.

The file object keeps track of where it is in the file, soif you call readline again, you get the next word:

The next word is “aah,” which is a perfectly legitimateword, so stop looking at me like that.Or, if it’s the whitespace that’s bothering you,we can get rid of it with the string method strip:

You can also use a file object as part of a for loop.This program reads words.txt and prints each word, oneper line:

Exercise 1

Write a program that reads 'words.txt' and prints only thewords with more than 20 characters (not counting whitespace).

Exercises[edit]

There are solutions to these exercises in the next section.You should at least attempt each one before you read the solutions.

Exercise 2

In 1939 Ernest Vincent Wright published a 50,000 word novel calledGadsby that does not contain the letter “e.” Since “e” isthe most common letter in English, that’s not easy to do.In fact, it is difficult to construct a solitary thought without usingthat most common symbol. It is slow going at first, but with cautionand hours of training you can gradually gain facility.

All right, I’ll stop now.

Write a function called has_no_e that returns 'True' ifthe given word doesn’t have the letter “e” in it.

Modify your program from the previous section to print only the wordsthat have no “e” and compute the percentage of the words in the listhave no “e.”

Exercise 3

Write a function named 'avoids'that takes a word and a string of forbidden letters, andthat returns 'True' if the word doesn’t use any of the forbiddenletters.Modify your program to prompt the user to enter a stringof forbidden letters and then print the number of words thatdon’t contain any of them.Can you find a combination of 5 forbidden letters thatexcludes the smallest number of words?

Exercise 4

Write a function named uses_only that takes a word and astring of letters, and that returns 'True' if the word containsonly letters in the list. Can you make a sentence using only theletters 'acefhlo'? Other than “Hoe alfalfa?”

Exercise 5

Write a function named uses_all that takes a word and astring of required letters, and that returns 'True' if the worduses all the required letters at least once. How many words are therethat use all the vowels 'aeiou'? How about 'aeiouy'?

Exercise 6

Write a function called is_abecedarian that returns'True' if the letters in a word appear in alphabetical order(double letters are ok). How many abecedarian words are there?

Search[edit]

All of the exercises in the previous section have somethingin common; they can be solved with the search pattern we sawin Section 8.6. The simplest example is:

The for loop traverses the characters in word. If we findthe letter “e”, we can immediately return False; otherwise wehave to go to the next letter. If we exit the loop normally, thatmeans we didn’t find an “e”, so we return True.

You can write this function more concisely using the inoperator, but I started with this version because it demonstrates the logic of the search pattern.

avoids is a more general version of has_no_e but ithas the same structure:

We can return False as soon as we find a forbidden letter;if we get to the end of the loop, we return True.

uses_only is similar except that the sense of the conditionis reversed:

Instead of a list of forbidden words, we have a list of availablewords. If we find a letter in word that is not inavailable, we can return False.

uses_all is similar except that we reverse the roleof the word and the string of letters:

Instead of traversing the letters in word, the looptraverses the required letters. If any of the required lettersdo not appear in the word, we can return False.

If you were really thinking like a computer scientist, you wouldhave recognized that uses_all was an instance of apreviously-solved problem, and you would have written:

This is an example of a program development method called problemrecognition, which means that you recognize the problem you areworking on as an instance of a previously-solved problem, and apply apreviously-developed solution.

Looping with indices[edit]

I wrote the functions in the previous section with forloops because I only needed the characters in the strings; I didn’thave to do anything with the indices.

For is_abecedarian we have to compare adjacent letters,which is a little tricky with a for loop:

An alternative is touse recursion:

Another option is to use a while loop:

The loop starts at i=0 and ends when i=len(word)-1. Eachtime through the loop, it compares the ith character (which you canthink of as the current character) to the i+1th character (which youcan think of as the next).

If the next character is less than (alphabetically before) the currentone, then we have discovered a break in the abecedarian trend, andwe return False.

If we get to the end of the loop without finding a fault, then theword passes the test. To convince yourself that the loop endscorrectly, consider an example like 'flossy'. Thelength of the word is 6, sothe last time the loop runs is when i is 4, which is theindex of the second-to-last character. On the last iteration,it compares the second-to-last character to the last, which iswhat we want.

Here is a version of is_palindrome (seeExercise 6.6) that uses two indices; one starts at thebeginning and goes up; the other starts at the end and goes down.

Or, if you noticed that this is an instance of a previously-solvedproblem, you might have written:

Assuming you did Exercise 8.8.

Debugging[edit]

Testing programs is hard. The functions in this chapter arerelatively easy to test because you can check the results by hand.Even so, it is somewhere between difficult and impossible to choose aset of words that test for all possible errors.

Taking has_no_e as an example, there are two obviouscases to check: words that have an ’e’ should return False;words that don’t should return True. You should have notrouble coming up with one of each.

Within each case, there are some less obvious subcases. Among thewords that have an “e,” you should test words with an “e” at thebeginning, the end, and somewhere in the middle. You should test longwords, short words, and very short words, like the empty string. Theempty string is an example of a special case, which is one ofthe non-obvious cases where errors often lurk.

In addition to the test cases you generate, you can also testyour program with a word list like words.txt. By scanningthe output, you might be able to catch errors, but be careful:you might catch one kind of error (words that should not beincluded, but are) and not another (words that should be included,but aren’t).

In general, testing can help you find bugs, but it is not easy togenerate a good set of test cases, and even if you do, you can’tbe sure your program is correct.

According to a legendary computer scientist:

Program testing can be used to show the presence of bugs, but never toshow their absence!— Edsger W. Dijkstra

Glossary[edit]

file object:
A value that represents an open file.
problem recognition:
A way of solving a problem byexpressing it as an instance of a previously-solved problem.
special case:
A test case that is atypical or non-obvious(and less likely to be handled correctly).

Exercises[edit]

Exercise 7[edit]

This question is based on a Puzzler that was broadcast on the radioprogram Car Talk[2]:

Give me a word with three consecutive double letters. I'll give you a

couple of words that almost qualify, but don't. For example, the wordcommittee, c-o-m-m-i-t-t-e-e. It would be great except for the ‘i’ thatsneaks in there. Or Mississippi: M-i-s-s-i-s-s-i-p-p-i. If you couldtake out those i’s it would work. But there is a word that has threeconsecutive pairs of letters and to the best of my knowledge this maybe the only word. Of course there are probably 500 more but I can onlythink of one. What is the word?

Write a program to find it. You can see my solution at'thinkpython.com/code/cartalk.py'.

Exercise 8[edit]

Here’s another Car Talk Puzzler[3]:

“I was driving on the highway the other day and I happened tonotice my odometer. Like most odometers, it shows six digits,in whole miles only. So, if my car had 300,000miles, for example, I’d see 3-0-0-0-0-0.“Now, what I saw that day was very interesting. I noticed that thelast 4 digits were palindromic; that is, they read the same forward asbackward. For example, 5-4-4-5 is a palindrome, so my odometercould have read 3-1-5-4-4-5.

“One mile later, the last 5 numbers were palindromic. For example, itcould have read 3-6-5-4-5-6. One mile after that, the middle 4 out of6 numbers were palindromic. And you ready for this? One mile later,all 6 were palindromic!

“The question is, what was on the odometer when I first looked?”

Write a Python program that tests all the six-digit numbers and printsany numbers that satisfy these requirements. You can see my solutionat 'thinkpython.com/code/cartalk.py'.

Exercise 9[edit]

Here’s another Car Talk Puzzler you can solve with asearch[4]:

“Recently I had a visit with my mom and we realized thatthe two digits that make up my age when reversed resulted in herage. For example, if she’s 73, I’m 37. We wondered how often this hashappened over the years but we got sidetracked with other topics andwe never came up with an answer.“When I got home I figured out that the digits of our ages have beenreversible six times so far. I also figured out that if we’re lucky itwould happen again in a few years, and if we’re really lucky it wouldhappen one more time after that. In other words, it would havehappened 8 times over all. So the question is, how old am I now?”

Write a Python program that searches for solutions to this Puzzler.Hint: you might find the string method 'zfill' useful.

You can see my solution at 'thinkpython.com/code/cartalk.py'.

Notes[edit]

  1. wikipedia.org/wiki/Moby_Project
  2. www.cartalk.com/content/puzzler/transcripts/200725
  3. www.cartalk.com/content/puzzler/transcripts/200803
  4. www.cartalk.com/content/puzzler/transcripts/200813

A list is a sequence[edit]

Like a string, a list is a sequence of values. In a string, thevalues are characters; in a list, they can be any type. The values inlist are called elements or sometimes items.

There are several ways to create a new list; the simplest is toenclose the elements in square brackets ([ and ]):

The first example is a list of four integers. The second is a list ofthree strings. The elements of a list don’t have to be the same type.The following list contains a string, a float, an integer, and(lo!) another list:

A list within another list is nested.

A list that contains no elements iscalled an empty list; you can create one with emptybrackets, [].

As you might expect, you can assign list values to variables:

Lists are mutable[edit]

The syntax for accessing the elements of a list is the same as foraccessing the characters of a string—the bracket operator. Theexpression inside the brackets specifies the index. Remember that theindices start at 0:

Unlike strings, lists are mutable. When the bracket operator appearson the left side of an assignment, it identifies the element of thelist that will be assigned.

The one-eth element of numbers, whichused to be 123, is now 5.

You can think of a list as a relationship between indices andelements. This relationship is called a mapping; each index“maps to” one of the elements. Here is a state diagram showing cheeses, numbers and empty:

<IMG SRC='book013.png'>

Lists are represented by boxes with the word “list” outsideand the elements of the list inside. cheeses refers toa list with three elements indexed 0, 1 and 2.numbers contains two elements; the diagram shows that thevalue of the second element has been reassigned from 123 to 5.empty refers to a list with no elements.

List indices work the same way as string indices:

  • Any integer expression can be used as an index.
  • If you try to read or write an element that does not exist, you get an IndexError.
  • If an index has a negative value, it counts backward from the end of the list.

The in operator also works on lists.

Traversing a list[edit]

The most common way to traverse the elements of a list iswith a for loop. The syntax is the same as for strings:

This works well if you only need to read the elements of thelist. But if you want to write or update the elements, youneed the indices. A common way to do that is to combinethe functions range and len:

This loop traverses the list and updates each element. lenreturns the number of elements in the list. range returnsa list of indices from 0 to n−1, where n is the length ofthe list. Each time through the loop i gets the indexof the next element. The assignment statement in the body usesi to read the old value of the element and to assign thenew value.

A for loop over an empty list never executes the body:

Although a list can contain another list, the nestedlist still counts as a single element. The length of this list isfour:

List operations[edit]

The + operator concatenates lists:

Similarly, the * operator repeats a list a given number of times:

The first example repeats [0] four times. The second examplerepeats the list [1, 2, 3] three times.

List slices[edit]

The slice operator also works on lists:

If you omit the first index, the slice starts at the beginning.If you omit the second, the slice goes to the end. So if youomit both, the slice is a copy of the whole list.

Since lists are mutable, it is often useful to make a copybefore performing operations that fold, spindle or mutilatelists.

A slice operator on the left side of an assignmentcan update multiple elements:

List methods[edit]

Python provides methods that operate on lists. For example,append adds a new element to the end of a list:

extend takes a list as an argument and appends all ofthe elements:

This example leaves t2 unmodified.

sort arranges the elements of the list from low to high:

List methods are all void; they modify the list and return None.If you accidentally write t = t.sort(), you will be disappointedwith the result.

Map, filter and reduce[edit]

To add up all the numbers in a list, you can use a loop like this:

total is initialized to 0. Each time through the loop,x gets one element from the list. The += operatorprovides a short way to update a variable:

is equivalent to:

As the loop executes, total accumulates the sum of theelements; a variable used this way is sometimes called anaccumulator.

Adding up the elements of a list is such a common operationthat Python provides it as a built-in function, sum:

An operation like this that combines a sequence of elements intoa single value is sometimes called reduce.

Sometimes you want to traverse one list while buildinganother. For example, the following function takes a list of stringsand returns a new list that contains capitalized strings:

res is initialized with an empty list; each time throughthe loop, we append the next element. So res is anotherkind of accumulator.

An operation like capitalize_all is sometimes called a map because it “maps” a function (in this case the method capitalize) onto each of the elements in a sequence.

Another common operation is to select some of the elements froma list and return a sublist. For example, the followingfunction takes a list of strings and returns a list that containsonly the uppercase strings:

isupper is a string method that returns True ifthe string contains only upper case letters.

An operation like only_upper is called a filter becauseit selects some of the elements and filters out the others.

Most common list operations can be expressed as a combinationof map, filter and reduce. Because these operations areso common, Python provides language features to support them,including the built-in function map and an operatorcalled a “list comprehension.”

Exercise 1[edit]

Write a function that takes a list of numbers and returns thecumulative sum; that is, a new list where the 'i'th elementis the sum of the first 'i+1' elements from the original list.For example, the cumulative sum of '[1, 2, 3]' is'[1, 3, 6]'.

Deleting elements[edit]

There are several ways to delete elements from a list. If youknow the index of the element you want, you can usepop:

pop modifies the list and returns the element that was removed.If you don’t provide an index, it deletes and returns thelast element.

If you don’t need the removed value, you can use the deloperator:

If you know the element you want to remove (but not the index), youcan use remove:

The return value from remove is None.

To remove more than one element, you can use del witha slice index:

As usual, the slice selects all the elements up to, but notincluding, the second index.

Lists and strings[edit]

A string is a sequence of characters and a list is a sequenceof values, but a list of characters is not the same as astring. To convert from a string to a list of characters,you can use list:

Because list is the name of a built-in function, you shouldavoid using it as a variable name. I also avoid l becauseit looks too much like 1. So that’s why I use t.

The list function breaks a string into individual letters. Ifyou want to break a string into words, you can use the splitmethod:

An optional argument called a delimiter specifies whichcharacters to use as word boundaries. The following example uses a hyphen as a delimiter:

join is the inverse of split. Ittakes a list of strings andconcatenates the elements. join is a string method,so you have to invoke it on the delimiter and pass thelist as a parameter:

In this case the delimiter is a space character, sojoin puts a space between words. To concatenatestrings without spaces, you can use the empty string,, as a delimiter.

Objects and values[edit]

If we execute these assignment statements:

We know that a and b both refer to astring, but we don’tknow whether they refer to the same string.There are two possible states:

In one case, a and b refer to two different objects thathave the same value. In the second case, they refer to the sameobject.

To check whether two variables refer to the same object, you canuse the is operator.

In this example, Python only created one string object,and both a and b refer to it.

But when you create two lists, you get two objects:

So the state diagram looks like this:

<IMG SRC='book015.png'>

In this case we would say that the two lists are equivalent,because they have the same elements, but not identical, becausethey are not the same object. If two objects are identical, they arealso equivalent, but if they are equivalent, they are not necessarilyidentical.

Until now, we have been using “object” and “value”interchangeably, but it is more precise to say that an object has avalue. If you execute a = [1,2,3], a refers to a listobject whose value is a particular sequence of elements. If anotherlist has the same elements, we would say it has the same value.

Aliasing[edit]

If a refers to an object and you assign b = a,then both variables refer to the same object:

The state diagram looks like this:

The association of a variable with an object is called a reference. In this example, there are two references to the sameobject.

An object with more than one reference has morethan one name, so we say that the object is aliased.

If the aliased object is mutable, changes made with one alias affectthe other:

Although this behavior can be useful, it is error-prone. In general,it is safer to avoid aliasing when you are working with mutableobjects.

For immutable objects like strings, aliasing is not as much of aproblem. In this example:

It almost never makes a difference whether a and b referto the same string or not.

List arguments[edit]

When you pass a list to a function, the function gets a referenceto the list.If the function modifies a list parameter, the caller sees the change.For example, delete_head removes the first element from a list:

Here’s how it is used:

The parameter t and the variable letters arealiases for the same object. The stack diagram looks likethis:

<IMG SRC='book017.png'>

Since the list is shared by two frames, I drewit between them.

It is important to distinguish between operations thatmodify lists and operations that create new lists. Forexample, the append method modifies a list, but the+ operator creates a new list:

This difference is important when you write functions thatare supposed to modify lists. For example, this functiondoes not delete the head of a list:

The slice operator creates a new list and the assignmentmakes t refer to it, but none of that has any effecton the list that was passed as an argument.

An alternative is to write a function that creates andreturns a new list. Forexample, tail returns all but the firstelement of a list:

This function leaves the original list unmodified.Here’s how it is used:

Exercise 2[edit]

Write a function called 'chop' that takes a list and modifiesit, removing the first and last elements, and returns 'None'.

Then write a function called 'middle' that takes a list andreturns a new list that contains all but the first and lastelements.

Debugging[edit]

Careless use of lists (and other mutable objects) can lead to long hours of debugging. Here are some common pitfalls and ways to avoid them:

  • Don’t forget that most list methods modify the argument and

return None. This is the opposite of the string methods,which return a new string and leave the original alone.If you are used to writing string code like this:

It is tempting to write list code like this:


Because sort returns None, thenext operation you perform with t is likely to fail.

Before using list methods and operators, you should read thedocumentation carefully and then test them in interactive mode. Themethods and operators that lists share with other sequences (likestrings) are documented atdocs.python.org/lib/typesseq.html. Themethods and operators that only apply to mutable sequencesare documented at docs.python.org/lib/typesseq-mutable.html.

  • Pick an idiom and stick with it.

Part of the problem with lists is that there are too manyways to do things. For example, to remove an element froma list, you can use pop, remove, del,or even a slice assignment.

To add an element, you can use the append method orthe + operator. But don’t forget that these are right:

And these are wrong:

Try out each of these examples in interactive mode to make sureyou understand what they do. Notice that only the lastone causes a runtime error; the other three are legal, but theydo the wrong thing.

  • Make copies to avoid aliasing.


If you want to use a method like sort that modifiesthe argument, but you need to keep the original list aswell, you can make a copy.

In this example you could also use the built-in function sorted,which returns a new, sorted list and leaves the original alone.But in that case you should avoid using sorted as a variablename!

Glossary[edit]

list:
A sequence of values.
element:
One of the values in a list (or other sequence),also called items.
index:
An integer value that indicates an element in a list.
nested list:
A list that is an element of another list.
list traversal:
The sequential accessing of each element in a list.
mapping:
A relationship in which each element of one setcorresponds to an element of another set. For example, a list isa mapping from indices to elements.
accumulator:
A variable used in a loop to add up oraccumulate a result.
reduce:
A processing pattern that traverses a sequence and accumulates the elements into a single result.
map:
A processing pattern that traverses a sequence andperforms an operation on each element.
filter:
A processing pattern that traverses a list andselects the elements that satisfy some criterion.
object:
Something a variable can refer to. An objecthas a type and a value.
equivalent:
Having the same value.
identical:
Being the same object (which implies equivalence).
reference:
The association between a variable and its value.
aliasing:
A circumstance where two variables refer to the sameobject.
delimiter:
A character or string used to indicate where astring should be split.

Exercises[edit]

Exercise 3[edit]

Write a function called is_sorted that takes a list as aparameter and returns 'True' if the list is sorted in ascendingorder and 'False' otherwise. You can assume (as a precondition)that the elements of the list can be compared with the comparisonoperators '<', '>', etc.

For example, is_sorted([1,2,2]) should return 'True'and is_sorted(['b','a']) should return 'False'.

Exercise 4[edit]

Two words are anagrams if you can rearrange the letters from oneto spell the other. Write a function called is_anagramthat takes two strings and returns 'True' if they are anagrams.

Exercise 5

The (so-called) Birthday Paradox:

Write a function called has_duplicates that takesa list and returns 'True' if there is any element thatappears more than once. It should not modify the originallist.

  • If there are 23 students in your class, what are the chances

that two of you have the same birthday? You can estimate thisprobability by generating random samples of 23 birthdaysand checking for matches. Hint: you can generate random birthdayswith the 'randint' function in the 'random' module.

You can read about this problem at'wikipedia.org/wiki/Birthday_paradox', and you can see my solutionat 'thinkpython.com/code/birthday.py'.

Exercise 6

Write a function called remove_duplicates that takesa list and returns a new list with only the unique elements fromthe original. Hint: they don’t have to be in the same order.

Exercise 7[edit]

Write a function that reads the file 'words.txt' and buildsa list with one element per word. Write two versions ofthis function, one using the 'append' method and theother using the idiom 't = t + [x]'. Which one takeslonger to run? Why?

You can see my solution at 'thinkpython.com/code/wordlist.py'.

Exercise 8[edit]

To check whether a word is in the word list, you could usethe 'in' operator, but it would be slow because it searchesthrough the words in order.

Because the words are in alphabetical order, we can speed things upwith a bisection search, which is similar to what you do when you looka word up in the dictionary. You start in the middle and check to seewhether the word you are looking for comes before the word in themiddle of the list. If so, then you search the first half of the listthe same way. Otherwise you search the second half.

Either way, you cut the remaining search space in half. If theword list has 113,809 words, it will take about 17 steps tofind the word or conclude that it’s not there.

Write a function called 'bisect' that takes a sorted listand a target value and returns the index of the valuein the list, if it’s there, or 'None' if it’s not.

Or you could read the documentation of the 'bisect' moduleand use that!

Exercise 9[edit]

Two words are a “reverse pair” if each is the reverse of theother. Write a program that finds all the reverse pairs in theword list.

Exercise 10[edit]

Two words “interlock” if taking alternating letters from each formsa new word1. For example, “shoe” and “cold”interlock to form “schooled.”

  • Write a program that finds all pairs of words that interlock.

Hint: don’t enumerate all pairs!

  • Can you find any words that are three-way interlocked; that is,

every third letter forms a word, starting from the first, second orthird?

1
This exercise is inspired by an example atpuzzlers.org.

A dictionary is like a list, but more general. In a list,the indices have to be integers; in a dictionary they canbe (almost) any type.

You can think of a dictionary as a mapping between a set of indices(which are called keys) and a set of values. Each key maps to avalue. The association of a key and a value is called a key-value pair or sometimes an item.

As an example, we'll build a dictionary that maps from Englishto Spanish words, so the keys and the values are all strings.

The function dict creates a new dictionary with no items.Because dict is the name of a built-in function, youshould avoid using it as a variable name.

The squiggly-brackets, {}, represent an empty dictionary.To add items to the dictionary, you can use square brackets:

This line creates an item that maps from the key’one’ to the value 'uno'. If we print thedictionary again, we see a key-value pair with a colonbetween the key and value:

This output format is also an input format. For example,you can create a new dictionary with three items:

But if you print eng2sp, you might be surprised:

The order of the key-value pairs is not the same. In fact, ifyou type the same example on your computer, you might get adifferent result. In general, the order of items ina dictionary is unpredictable.

But that’s not a problem becausethe elements of a dictionary are never indexed with integer indices.Instead, you use the keys to look up the corresponding values:

The key ’two’ always maps to the value 'dos' so the orderof the items doesn’t matter.

If the key isn’t in the dictionary, you get an exception:

The len function works on dictionaries; it returns thenumber of key-value pairs:

The in operator works on dictionaries; it tells you whethersomething appears as a key in the dictionary (appearingas a value is not good enough).

To see whether something appears as a value in a dictionary, youcan use the method values, which returns the values asa list, and then use the in operator:

You can do the same with keys:

The in operator uses different algorithms for lists anddictionaries. For lists, it uses a search algorithm, as inSection 8.6. As the list gets longer, the search time getslonger in direct proportion. For dictionaries, Python uses analgorithm called a hashtable that has a remarkable property: thein operator takes about the same amount of time no matter howmany items there are in a dictionary. I won’t explain how that’spossible, but you can read more about it atwikipedia.org/wiki/Hash_table.

Exercise 1[edit]

Write a function that reads the words in 'words.txt' andstores them as keys in a dictionary. It doesn’t matter what thevalues are. Then you can use the 'in' operatoras a fast way to check whether a string is inthe dictionary.

If you did Exercise '10.8', you can compare the speedof this implementation with the list 'in' operator and thebisection search.

Dictionary as a set of counters[edit]

Suppose you are given a string and you want to count how manytimes each letter appears. There are several ways you could do it:

  • You could create 26 variables, one for each letter of the alphabet. Then you could traverse the string and, for each character, increment the corresponding counter, probably using a chained conditional.
  • You could create a list with 26 elements. Then you could convert each character to a number (using the built-in function ord), use the number as an index into the list, and increment the appropriate counter.
  • You could create a dictionary with characters as keys and counters as the corresponding values. The first time you see a character, you would add an item to the dictionary. After that you would increment the value of an existing item.

Each of these options performs the same computation, but eachof them implements that computation in a different way.

An implementation is a way of performing a computation;some implementations are better than others. For example,an advantage of the dictionary implementation is that we don’thave to know ahead of time which letters appear in the stringand we only have to make room for the letters that do appear.

Here is what the code might look like:

The name of the function is histogram, which is a statisticalterm for a set of counters (or frequencies).

The first line of thefunction creates an empty dictionary. The for loop traversesthe string. Each time through the loop, if the character c isnot in the dictionary, we create a new item with key c and theinitial value 1 (since we have seen this letter once). If c isalready in the dictionary we increment d[c].

Here’s how it works:

The histogram indicates that the letters ’a’ and 'b'appear once; 'o' appears twice, and so on.

Exercise 2[edit]

Dictionaries have a method called 'get' that takes a keyand a default value. If the key appears in the dictionary,'get' returns the corresponding value; otherwise it returnsthe default value. For example:

Use 'get' to write 'histogram' more concisely. Youshould be able to eliminate the 'if' statement.

Looping and dictionaries[edit]

If you use a dictionary in a for statement, it traversesthe keys of the dictionary. For example, print_histprints each key and the corresponding value:

Here’s what the output looks like:

Again, the keys are in no particular order.

Exercise 3[edit]

Dictionaries have a method called 'keys' that returnsthe keys of the dictionary, in no particular order, as a list.

Modify print_hist to print the keys and their valuesin alphabetical order.

Reverse lookup[edit]

Given a dictionary d and a key k, it is easy tofind the corresponding value v = d[k]. This operationis called a lookup.

But what if you have v and you want to find k?You have two problems: first, there might be more than onekey that maps to the value v. Depending on the application,you might be able to pick one, or you might have to makea list that contains all of them. Second, there is nosimple syntax to do a reverse lookup; you have to search.

Here is a function that takes a value and returns the firstkey that maps to that value:

This function is yet another example of the search pattern, but ituses a feature we haven’t seen before, raise. The raisestatement causes an exception; in this case it causes a ValueError, which generally indicates that there is something wrongwith the value of a parameter.

If we get to the end of the loop, that means vdoesn’t appear in the dictionary as a value, so we raise anexception.

Here is an example of a successful reverse lookup:

And an unsuccessful one:

The result when you raise an exception is the same as whenPython raises one: it prints a traceback and an error message.

The raise statement takes a detailed error message as anoptional argument. For example:

A reverse lookup is much slower than a forward lookup; if youhave to do it often, or if the dictionary gets big, the performanceof your program will suffer.

Exercise 4

Modify reverse_lookup so that it builds and returns a listof all keys that map to 'v', or an empty list if thereare none.

Dictionaries and lists[edit]

Lists can appear as values in a dictionary. For example, if youwere given a dictionary that maps from letters to frequencies, youmight want to invert it; that is, create a dictionary that mapsfrom frequencies to letters. Since there might be several letterswith the same frequency, each value in the inverted dictionaryshould be a list of letters.

Here is a function that inverts a dictionary:

Each time through the loop, key gets a key from d and val gets the corresponding value. If val is not in inv,that means we haven’t seen it before, so we create a new item andinitialize it with a singleton (a list that contains asingle element). Otherwise we have seen this value before, so weappend the corresponding key to the list.

Here is an example:

And here is a diagram showing hist and inv:

A dictionary is represented as a box with the type dict above itand the key-value pairs inside. If the values are integers, floats orstrings, I usually draw them inside the box, but I usually draw listsoutside the box, just to keep the diagram simple.

Lists can be values in a dictionary, as this example shows, but theycannot be keys. Here’s what happens if you try:

I mentioned earlier that a dictionary is implemented usinga hashtable and that means that the keys have to be hashable.

A hash is a function that takes a value (of any kind)and returns an integer. Dictionaries use these integers,called hash values, to store and look up key-value pairs.

This system works fine if the keys are immutable. But if thekeys are mutable, like lists, bad things happen. For example,when you create a key-value pair, Python hashes the key and stores it in the corresponding location. If you modify thekey and then hash it again, it would go to a different location.In that case you might have two entries for the same key,or you might not be able to find a key. Either way, thedictionary wouldn’t work correctly.

That’s why the keys have to be hashable, and why mutable types likelists aren’t. The simplest way to get around this limitation is touse tuples, which we will see in the next chapter.

Since dictionaries are mutable, they can’t be used as keys,but they can be used as values.

Exercise 5[edit]

Read the documentation of the dictionary method 'setdefault'and use it to write a more concise version of invert_dict.

Memos[edit]

If you played with the fibonacci function fromSection 6.7, you might have noticed that the biggerthe argument you provide, the longer the function takes to run.Furthermore, the run time increases very quickly.

To understand why, consider this call graph forfibonacci with n=4:

<IMG SRC='book019.png'>

A call graph shows a set of function frames, with lines connecting eachframe to the frames of the functions it calls. At the top of thegraph, fibonacci with n=4 calls fibonacci with n=3 and n=2. In turn, fibonacci with n=3 callsfibonacci with n=2 and n=1. And so on.

Count how many times fibonacci(0) and fibonacci(1) arecalled. This is an inefficient solution to the problem, and it getsworse as the argument gets bigger.

One solution is to keep track of values that have already beencomputed by storing them in a dictionary. A previously computed valuethat is stored for later use is called a memo[1]. Here is animplementation of fibonacci using memos:

known is a dictionary that keeps track of the Fibonaccinumbers we already know. It starts withtwo items: 0 maps to 0 and 1 maps to 1.

Whenever fibonacci is called, it checks known.If the result is already there, it can returnimmediately. Otherwise it has to compute the new value, add it to the dictionary, and return it.

Exercise 6[edit]

Run this version of 'fibonacci' and the original witha range of parameters and compare their run times.

Global variables[edit]

In the previous example, known is created outside the function,so it belongs to the special frame called __main__.Variables in __main__ are sometimes called globalbecause they can be accessed from any function. Unlike localvariables, which disappear when their function ends, global variablespersist from one function call to the next.

It is common to use global variables for flags; that is, boolean variables that indicate (“flag”) whether a conditionis true. For example, some programs usea flag named verbose to control the level of detail in theoutput:

If you try to reassign a global variable, you might be surprised.The following example is supposed to keep track of whether thefunction has been called:

But if you run it you will see that the value of been_calleddoesn’t change. The problem is that example2 creates a new localvariable named been_called. The local variable goes away whenthe function ends, and has no effect on the global variable.

To reassign a global variable inside a function you have todeclare the global variable before you use it:

The global statement tells the interpretersomething like, “In this function, when I say been_called, Imean the global variable; don’t create a local one.”

Here’s an example that tries to update a global variable:

If you run it you get:

Python assumes that count is local, which meansthat you are reading it before writing it. The solution, again,is to declare count global.

If the global value is mutable, you can modify it withoutdeclaring it:

So you can add, remove and replace elements of a global list ordictionary, but if you want to reassign the variable, youhave to declare it:

Long integers[edit]

If you compute fibonacci(50), you get:

The L at the end indicates that the result is a longinteger[2], or type long.

Values with type int have a limited range;long integers can be arbitrarily big, but as they get biggerthey consume more space and time.

The mathematical operators work on long integers, and the functionsin the math module, too, so in general any code thatworks with int will also work with long.

Any time the result of a computation is too big to be represented withan integer, Python converts the result as a long integer:

In the first case the result has type int; in thesecond case it is long.

Exercise 7[edit]

Exponentiation of large integers is the basis of commonalgorithms for public-key encryption. Read the Wikipediapage on the RSA algorithm[3]and write functions to encode and decode messages.

Debugging[edit]

As you work with bigger datasets it can become unwieldy todebug by printing and checking data by hand. Here are somesuggestions for debugging large datasets:

Scale down the input:
If possible, reduce the size of thedataset. For example if the program reads a text file, start withjust the first 10 lines, or with the smallest example you can find.You can either edit the files themselves, or (better) modify theprogram so it reads only the first n lines.If there is an error, you can reduce n to the smallestvalue that manifests the error, and then increase it graduallyas you find and correct errors.
Check summaries and types:
Instead of printing and checking theentire dataset, consider printing summaries of the data: for example,the number of items in a dictionary or the total of a list of numbers.A common cause of runtime errors is a value that is not the righttype. For debugging this kind of error, it is often enough to printthe type of a value.
Write self-checks:
Sometimes you can write code to checkfor errors automatically. For example, if you are computing theaverage of a list of numbers, you could check that the result isnot greater than the largest element in the list or less thanthe smallest. This is called a “sanity check” because it detectsresults that are “insane.”Another kind of check compares the results of two differentcomputations to see if they are consistent. This is called a“consistency check.”
Pretty print the output:
Formatting debugging outputcan make it easier to spot an error. We saw an example inSection 6.9. The pprint module providesa pprint function that displays built-in types ina more human-readable format.

Again, time you spend building scaffolding can reducethe time you spend debugging.

Glossary[edit]

dictionary:
A mapping from a set of keys to theircorresponding values.
key-value pair:
The representation of the mapping froma key to a value.
item:
Another name for a key-value pair.
key:
An object that appears in a dictionary as thefirst part of a key-value pair.
value:
An object that appears in a dictionary as thesecond part of a key-value pair. This is more specific thanour previous use of the word “value.”
implementation:
A way of performing a computation.
hashtable:
The algorithm used to implement Pythondictionaries.
hash function:
A function used by a hashtable to compute thelocation for a key.
hashable:
A type that has a hash function. Immutabletypes like integers,floats and strings are hashable; mutable types like lists anddictionaries are not.
lookup:
A dictionary operation that takes a key and findsthe corresponding value.
reverse lookup:
A dictionary operation that takes a value and findsone or more keys that map to it.
singleton:
A list (or other sequence) with a single element.
call graph:
A diagram that shows every frame created duringthe execution of a program, with an arrow from each caller toeach callee.
histogram:
A set of counters.
memo:
A computed value stored to avoid unnecessary future computation.
global variable:
A variable defined outside a function. Globalvariables can be accessed from any function.
flag:
A boolean variable used to indicate whether a conditionis true.
declaration:
A statement like global that tells theinterpreter something about a variable.

Exercise-8[edit]

no particular order, as a list.Modify print_hist to print the keys and their values in alphabetical order.

Exercise 9[edit]

Two words are “rotate pairs” if you can rotate one of themand get the other (see rotate_word in Exercise '8.12').

Write a program that reads a wordlist and finds all the rotatepairs.

Exercise 10[edit]

Here’s another Puzzler from CarTalk[4]:

This was sent in by a fellow named Dan O’Leary. He came upon a commonone-syllable, five-letter word recently that has the following uniqueproperty. When you remove the first letter, the remaining letters forma homophone of the original word, that is a word that sounds exactlythe same. Replace the first letter, that is, put it back and removethe second letter and the result is yet another homophone of theoriginal word. And the question is, what’s the word?Now I’m going to give you an example that doesn’t work. Let’s look atthe five-letter word, ‘wrack.’ W-R-A-C-K, you know like to ‘wrack withpain.’ If I remove the first letter, I am left with a four-letterword, ’R-A-C-K.’ As in, ‘Holy cow, did you see the rack on that buck!It must have been a nine-pointer!’ It’s a perfect homophone. If youput the ‘w’ back, and remove the ‘r,’ instead, you’re left with theword, ‘wack,’ which is a real word, it’s just not a homophone of theother two words.

But there is, however, at least one word that Dan and we know of,which will yield two homophones if you remove either of the first twoletters to make two, new four-letter words. The question is, what’sthe word?

'

You can use the dictionary from Exercise '11.1' to checkwhether a string is in the word list.

To check whether two words are homophones, you can use the CMUPronouncing Dictionary. You can download it from'www.speech.cs.cmu.edu/cgi-bin/cmudict' or from'thinkpython.com/code/c06d' and you can also download'thinkpython.com/code/pronounce.py', which provides a functionnamed read_dictionary that reads the pronouncing dictionary andreturns a Python dictionary that maps from each word to a string thatdescribes its primary pronunciation.

Write a program that lists all the words that solve the Puzzler.You can see my solution at 'thinkpython.com/code/homophone.py'.

Notes[edit]

  1. Seewikipedia.org/wiki/Memoization
  2. In Python 3.0, type long is gone; all integers,even really big ones, are type int.
  3. wikipedia.org/wiki/RSA
  4. www.cartalk.com/content/puzzler/transcripts/200717

Tuples are immutable[edit]

A tuple is a sequence of values. The values can be any type, andthey are indexed by integers, so in that respect tuples are a lotlike lists. The important difference is that tuples are immutable.

Syntactically, a tuple is a comma-separated list of values:

Although it is not necessary, it is common to enclose tuples inparentheses:

To create a tuple with a single element, you have to include the finalcomma:

Without the comma, Python treats ('a') as a string inparentheses:

Another way to create a tuple is the built-in function tuple.With no argument, it creates an empty tuple:

If the argument is a sequence (string, list or tuple), the resultis a tuple with the elements of the sequence:

Because tuple is the name of a built-in function, you shouldavoid using it as a variable name.

Most list operators also work on tuples. The bracket operatorindexes an element:

And the slice operator selects a range of elements.

But if you try to modify one of the elements of the tuple, you getan error:

You can’t modify the elements of a tuple, but you can replaceone tuple with another:

Tuple assignment[edit]

It is often useful to swap the values of two variables.With conventional assignments, you have to use a temporaryvariable. For example, to swap a and b:

This solution is cumbersome; tuple assignment is more elegant:

The left side is a tuple of variables; the right side is a tuple ofexpressions. Each value is assigned to its respective variable. All the expressions on the right side are evaluated before anyof the assignments.

The number of variables on the left and the number ofvalues on the right have to be the same:

More generally, the right side can be any kind of sequence(string, list or tuple). For example, to split an email addressinto a user name and a domain, you could write:

The return value from split is a list with two elements;the first element is assigned to uname, the second todomain.

Tuples as return values[edit]

Strictly speaking, a function can only return one value, butif the value is a tuple, the effect is the same as returningmultiple values. For example, if you want to divide two integersand compute the quotient and remainder, it is inefficient tocompute x/y and then x%y. It is better to computethem both at the same time.

The built-in function divmod takes two arguments andreturns a tuple of two values, the quotient and remainder.You can store the result as a tuple:

Or use tuple assignment to store the elements separately:

Here is an example of a function that returns a tuple:

max and min are built-in functions that findthe largest and smallest elements of a sequence. min_maxcomputes both and returns a tuple of two values.

Variable-length argument tuples[edit]

Functions can take a variable number of arguments. A parametername that begins with *gathers arguments intoa tuple. For example, printalltakes any number of arguments and prints them:

The gather parameter can have any name you like, but args isconventional. Here’s how the function works:

You can combine the gather operator with required and positionalarguments:

Run this function with 1, 2, 3 and 4 or more arguments andmake sure you understand what it does.

The complement of gather is scatter. If you have asequence of values and you want to pass it to a functionas multiple arguments, you can use the * operator.For example, divmod takes exactly two arguments; itdoesn’t work with a tuple:

But if you scatter the tuple, it works:

Exercise 1[edit]

Many of the built-in functions usevariable-length argument tuples. For example, 'max'and 'min' can take any number of arguments:

But 'sum' does not.

Write a function called 'sumall' that takes any numberof arguments and returns their sum.

Lists and tuples[edit]

zip is a built-in function that takes two or more sequences and“zips” them into a list1 of tuples where each tuple contains one element from eachsequence.

This example zips a string and a list:

The result is a list of tuples where each tuple containsa character from the string and the corresponding element fromthe list.

If the sequences are not the same length, the result has thelength of the shorter one.

You can use tuple assignment in a for loop to traverse a list oftuples:

Each time through the loop, Python selects the next tuple inthe list and assigns the elements to letter and number. The output of this loop is:

If you combine zip, for and tuple assignment, you get auseful idiom for traversing two (or more) sequences at the sametime. For example, has_match takes two sequences, t1 andt2, and returns True if there is an index isuch that t1[i] t2[i]:

If you need to traverse the elements of a sequence and theirindices, you can use the built-in function enumerate:

The output of this loop is:

Again.

Dictionaries and tuples[edit]

Dictionaries have a method called items that returns a list oftuples, where each tuple is a key-value pair2.

As you should expect from a dictionary, the items are in noparticular order.

Conversely, you can use a list of tuples to initializea new dictionary:

Combining dict with zip yields a concise wayto create a dictionary:

The dictionary method update also takes a list of tuplesand adds them, as key-value pairs, to an existing dictionary.

Combining items, tuple assignment and for, youget the idiom for traversing the keys and values of a dictionary:

The output of this loop is:

Again.

It is common to use tuples as keys in dictionaries (primarily becauseyou can’t use lists). For example, a telephone directory might mapfrom last-name, first-name pairs to telephone numbers. Assumingthat we have defined last, first and number, wecould write:

The expression in brackets is a tuple. We could use tupleassignment to traverse this dictionary.

This loop traverses the keys in directory, which are tuples. Itassigns the elements of each tuple to last and first, thenprints the name and corresponding telephone number.

There are two ways to represent tuples in a state diagram. The moredetailed version shows the indices and elements just as they appear ina list. For example, the tuple ('Cleese', 'John') would appear:

<IMG SRC='book020.png'>

But in a larger diagram you might want to leave out thedetails. For example, a diagram of the telephone directory mightappear:

Here the tuples are shown using Python syntax as a graphicalshorthand.

The telephone number in the diagram is the complaints line for theBBC, so please don’t call it.

Comparing tuples[edit]

The comparison operators work with tuples and other sequences;Python starts by comparing the first element from eachsequence. If they are equal, it goes on to the next elements,and so on, until it finds elements that differ. Subsequentelements are not considered (even if they are really big).

The sort function works the same way. It sorts primarily by first element, but in the case of a tie, it sortsby second element, and so on.

This feature lends itself to a pattern called DSU for

Decorate
a sequence by building a list of tupleswith one or more sort keys preceding the elements from the sequence,
Sort
the list of tuples, and
Undecorate
by extracting the sorted elements of the sequence.

For example, suppose you have a list of words and you want tosort them from longest to shortest:

The first loop builds a list of tuples, where eachtuple is a word preceded by its length.

sort compares the first element, length, first, andonly considers the second element to break ties. The keyword argumentreverse=True tells sort to go in decreasing order.

The second loop traverses the list of tuples and builds a list ofwords in descending order of length.

Exercise 2[edit]

In this example, ties are broken by comparing words, so wordswith the same length appear in alphabetical order. For otherapplications you might want to break ties at random. Modifythis example so that words with the same length appear inrandom order. Hint: see the 'random' function in the'random' module.

Sequences of sequences[edit]

I have focused on lists of tuples, but almost all of the examples inthis chapter also work with lists of lists, tuples of tuples, andtuples of lists. To avoid enumerating the possible combinations, itis sometimes easier to talk about sequences of sequences.

In many contexts, the different kinds of sequences (strings, lists andtuples) can be used interchangeably. So how and why do you choose oneover the others?

To start with the obvious, strings are more limited than othersequences because the elements have to be characters. They arealso immutable. If you need the ability to change the charactersin a string (as opposed to creating a new string), you mightwant to use a list of characters instead.

Lists are more common than tuples, mostly because they are mutable.But there are a few cases where you might prefer tuples:

  • In some contexts, like a return statement, it is syntactically simpler to create a tuple than a list. In other contexts, you might prefer a list.
  • If you want to use a sequence as a dictionary key, you have to use an immutable type like a tuple or string.
  • If you are passing a sequence as an argument to a function, using tuples reduces the potential for unexpected behavior due to aliasing.

Because tuples are immutable, they don’t provide methodslike sort and reverse, which modify existing lists.But Python provides the built-in functions sortedand reversed, which take any sequence as a parameterand return a new list with the same elements in a differentorder.

Debugging[edit]

Lists, dictionaries and tuples are known generically as datastructures; in this chapter we are starting to see compound datastructures, like lists of tuples, and dictionaries that contain tuplesas keys and lists as values. Compound data structures are useful, butthey are prone to what I call shape errors; that is, errorscaused when a data structure has the wrong type, size or composition.For example, if you are expecting a list with one integer and Igive you a plain old integer (not in a list), it won’t work.

To help debug these kinds of errors, I have written a modulecalled structshape that provides a function, also calledstructshape, that takes any kind of data structure asan argument and returns a string that summarizes its shape.You can download it from thinkpython.com/code/structshape.py

Here’s the result for a simple list:

A fancier program might write “list of 3 ints,” but itwas easier not to deal with plurals. Here’s a list of lists:

If the elements of the list are not the same type,structshape groups them, in order, by type:

Here’s a list of tuples:

And here’s a dictionary with 3 items that map integers to strings.

If you are having trouble keeping track of your data structures,structshape can help.

Glossary[edit]

tuple:
An immutable sequence of elements.
tuple assignment:
An assignment with a sequence on theright side and a tuple of variables on the left. The rightside is evaluated and then its elements are assigned to thevariables on the left.
gather:
The operation of assembling a variable-lengthargument tuple.
scatter:
The operation of treating a sequence as a list ofarguments.
DSU:
Abbreviation of “decorate-sort-undecorate,” apattern that involves building a list of tuples, sorting, andextracting part of the result.
data structure:
A collection of related values, oftenorganized in lists, dictionaries, tuples, etc.
shape (of a data structure):
A summary of the type,size and composition of a data structure.

Exercises[edit]

Exercise 3[edit]

Write a function called most_frequent that takes a string andprints the letters in decreasing order of frequency. Find textsamples from several different languages and see how letter frequencyvaries between languages. Compare your results with the tables at'wikipedia.org/wiki/Letter_frequencies'.

Exercise 4[edit]

More anagrams!

  • Write a program

that reads a word list from a file (see Section '9.1') andprints all the sets of words that are anagrams.Here is an example of what the output might look like:

Hint: you might want to build a dictionary that maps from aset of letters to a list of words that can be spelled with thoseletters. The question is, how can you represent the set ofletters in a way that can be used as a key?

  • Modify the previous program so that it prints the largest set

of anagrams first, followed by the second largest set, and so on.

  • In Scrabble a “bingo” is when you play all seven tiles in

your rack, along with a letter on the board, to form an eight-letterword. What set of 8 letters forms the most possible bingos?Hint: there are seven.

  • 'Two words form a “metathesis pair” if you can transform one

into the other by swapping two letters''3''; for example,“converse” and “conserve.” Write a program that finds all ofthe metathesis pairs in the dictionary. Hint: don’t test all pairsof words, and don’t test all possible swaps.'You can download a solution from ''thinkpython.com/code/anagram_sets.py''.'

Exercise 5[edit]

Here’s another Car Talk Puzzler4:

What is the longest English word, that remains a valid English word,as you remove its letters one at a time?Now, letters can be removed from either end, or the middle, but youcan’t rearrange any of the letters. Every time you drop a letter, youwind up with another English word. If you do that, you’re eventuallygoing to wind up with one letter and that too is going to be anEnglish word—one that’s found in the dictionary. I want to knowwhat’s the longest word and how many letters does ithave?

I’m going to give you a little modest example: Sprite. Ok? You startoff with sprite, you take a letter off, one from the interior of theword, take the r away, and we’re left with the word spite, then wetake the e off the end, we’re left with spit, we take the s off, we’releft with pit, it, and I.

Write a program to find all words that can be reduced in this way,and then find the longest one.

This exercise is a little more challenging than most, so here aresome suggestions:

  • You might want to write a function that takes a word and

computes a list of all the words that can be formed by removing oneletter. These are the “children” of the word.

  • Recursively, a word is reducible if any of its children

are reducible. As a base case, you can consider the emptystring reducible.

  • The wordlist I provided, 'words.txt', doesn’t

contain single letter words. So you might want to add“I”, “a”, and the empty string.

  • To improve the performance of your program, you might want

to memoize the words that are known to be reducible.

You can see my solution at 'thinkpython.com/code/reducible.py'.

1
In Python 3.0, zip returns aniterator of tuples, but for most purposes, an iterator behaves likea list.
2
This behavior isslightly different in Python 3.0.
3
This exercise isinspired by an example at puzzlers.org.
4
www.cartalk.com/content/puzzler/transcripts/200651

= Case study: data structure selection}}

Word frequency analysis[edit]

As usual, you should at least attempt the following exercisesbefore you read my solutions.

Exercise 1[edit]

Write a program that reads a file, breaks each line intowords, strips whitespace and punctuation from the words, andconverts them to lowercase.

Hint: The 'string' module provides strings named 'whitespace',which contains space, tab, newline, etc., and 'punctuation' which contains the punctuation characters. Let’s seeif we can make Python swear:

Also, you might consider using the string methods 'strip','replace' and 'translate'.

Exercise 2[edit]

Go to Project Gutenberg ('gutenberg.org') and download your favorite out-of-copyright book in plain text format.

Modify your program from the previous exercise to read the bookyou downloaded, skip over the header information at the beginningof the file, and process the rest of the words as before.

Then modify the program to count the total number of words inthe book, and the number of times each word is used.

Print the number of different words used in the book. Comparedifferent books by different authors, written in different eras.Which author uses the most extensive vocabulary?

Exercise 3[edit]

Modify the program from the previous exercise to print the20 most frequently-used words in the book.

Exercise 4[edit]

Modify the previous program to read a word list (seeSection '9.1') and then print all the words in the book thatare not in the word list. How many of them are typos? How many ofthem are common words that should be in the word list, and howmany of them are really obscure?

Random numbers[edit]

Given the same inputs, most computer programs generate the sameoutputs every time, so they are said to be deterministic.Determinism is usually a good thing, since we expect the samecalculation to yield the same result. For some applications, though,we want the computer to be unpredictable. Games are an obviousexample, but there are more.

Making a program truly nondeterministic turns out to be not so easy,but there are ways to make it at least seem nondeterministic. One ofthem is to use algorithms that generate pseudorandom numbers.Pseudorandom numbers are not truly random because they are generatedby a deterministic computation, but just by looking at the numbers itis all but impossible to distinguish them from random.

The random module provides functions that generatepseudorandom numbers (which I will simply call “random” fromhere on).

The function random returns a random floatbetween 0.0 and 1.0 (including 0.0 but not 1.0). Each time youcall random, you get the next number in a long series. To see asample, run this loop:

The function randint takes parameters low andhigh and returns an integer between low andhigh (including both).

To choose an element from a sequence at random, you can usechoice:

The random module also provides functions to generaterandom values from continuous distributions includingGaussian, exponential, gamma, and a few more.

Exercise 5[edit]

Write a function named choose_from_hist that takesa histogram as defined in Section '11.1' and returns a random value from the histogram, chosen with probabilityin proportion to frequency. For example, for this histogram:

your function should '’a’' with probability '2/3' and bwith probability '1/3'.

Word histogram[edit]

Here is a program that reads a file and builds a histogram of thewords in the file:

This program reads emma.txt, which contains the text of Emma by Jane Austen.

process_file loops through the lines of the file,passing them one at a time to process_line. The histogramh is being used as an accumulator.

process_line uses the string method replace to replacehyphens with spaces before using split to break the line into alist of strings. It traverses the list of words and uses stripand lower to remove punctuation and convert to lower case. (Itis a shorthand to say that strings are “converted;” remember thatstring are immutable, so methods like strip and lowerreturn new strings.)

Finally, process_line updates the histogram by creating a newitem or incrementing an existing one.

To count the total number of words in the file, we can add upthe frequencies in the histogram:

The number of different words is just the number of items inthe dictionary:

Here is some code to print the results:

And the results:

Most common words[edit]

To find the most common words, we can apply the DSU pattern;most_common takes a histogram and returns a list ofword-frequency tuples, sorted in reverse order by frequency:

Here is a loop that prints the ten most common words:

And here are the results from Emma:

Optional parameters[edit]

We have seen built-in functions and methods that take a variablenumber of arguments. It is possible to write user-defined functionswith optional arguments, too. For example, here is a function thatprints the most common words in a histogram

The first parameter is required; the second is optional.The default value of num is 10.

If you only provide one argument:

num gets the default value. If you provide two arguments:

num gets the value of the argument instead. In otherwords, the optional argument overrides the default value.

If a function has both required and optional parameters, allthe required parameters have to come first, followed by theoptional ones.

Dictionary subtraction[edit]

Finding the words from the book that are not in the word listfrom words.txt is a problem you might recognize as setsubtraction; that is, we want to find all the words from oneset (the words in the book) that are not in another set (thewords in the list).

subtract takes dictionaries d1 and d2 and returns anew dictionary that contains all the keys from d1 that are notin d2. Since we don’t really care about the values, weset them all to None.

To find the words in the book that are not in words.txt,we can use process_file to build a histogram forwords.txt, and then subtract:

Here are some of the results from Emma:

Some of these words are names and possessives. Others, like“rencontre,” are no longer in common use. But a few are commonwords that should really be in the list!

Exercise 6[edit]

Python provides a data structure called 'set' that provides manycommon set operations. Read the documentation at'docs.python.org/lib/types-set.html' and write a programthat uses set subtraction to find words in the book that are not inthe word list.

Random words[edit]

To choose a random word from the histogram, the simplest algorithmis to build a list with multiple copies of each word, accordingto the observed frequency, and then choose from the list:

The expression [word] * freq creates a list with freqcopies of the string word. The extendmethod is similar to append except that the argument isa sequence.

Exercise 7[edit]

This algorithm works, but it is not very efficient; each time youchoose a random word, it rebuilds the list, which is as big asthe original book. An obvious improvement is to build the listonce and then make multiple selections, but the list is still big.

An alternative is:

  • Use 'keys' to get a list of the words in the book.
  • Build a list that contains the cumulative sum of the word

frequencies (see Exercise '10.1'). The last itemin this list is the total number of words in the book, 'n'.

  • Choose a random number from 1 to 'n'. Use a bisection search

(See Exercise '10.8') to find the index where the randomnumber would be inserted in the cumulative sum.

  • Use the index to find the corresponding word in the word list.

Write a program that uses this algorithm to choose a randomword from the book.

Markov analysis[edit]

If you choose words from the book at random, you can get asense of the vocabulary, you probably won’t get a sentence:

A series of random words seldom makes sense because thereis no relationship between successive words. For example, ina real sentence you would expect an article like “the” tobe followed by an adjective or a noun, and probably not a verbor adverb.

One way to measure these kinds of relationships is Markovanalysis, which characterizes, for a given sequence of words,the probability of the word that comes next. For example,the song Eric, the Half a Bee begins:

Half a bee, philosophically,
Must, ipso facto, half not be.
But half the bee has got to be
Vis a vis, its entity. D’you see?
But can a bee be said to be
Or not to be an entire bee
When half the bee is not a bee
Due to some ancient injury?

In this text,the phrase “half the” is always followed by the word “bee,”but the phrase “the bee” might be followed by either“has” or “is”.

The result of Markov analysis is a mapping from each prefix(like “half the” and “the bee”) to all possible suffixes(like “has” and “is”).

Given this mapping, you can generate a random text bystarting with any prefix and choosing at random from thepossible suffixes. Next, you can combine the end of theprefix and the new suffix to form the next prefix, and repeat.

For example, if you start with the prefix “Half a,” then thenext word has to be “bee,” because the prefix only appearsonce in the text. The next prefix is “a bee,” so thenext suffix might be “philosophically,” “be” or “due.”

In this example the length of the prefix is always two, butyou can do Markov analysis with any prefix length. The lengthof the prefix is called the “order” of the analysis.

Exercise 8[edit]

Markov analysis:

  • Write a program to read a text from a file and perform Markov analysis. The result should be a dictionary that maps from prefixes to a collection of possible suffixes. The collection might be a list, tuple, or dictionary; it is up to you to make an appropriate choice. You can test your program with prefix length two, but you should write the program in a way that makes it easy to try other lengths.
  • Add a function to the previous program to generate random text based on the Markov analysis. Here is an example from Emma with prefix length 2:

He was very clever, be it sweetness or be angry, ashamed or only

amused, at such a stroke. She had never thought of Hannah till youwere never meant for me?' 'I cannot make speeches, Emma:' he soon cutit all himself.

For this example, I left the punctuation attached to the words. The result is almost syntactically correct, but not quite. Semantically, it almost makes sense, but not quite.

  • What happens if you increase the prefix length? Does the random text make more sense?
  • Once your program is working, you might want to try a mash-up: if you analyze text from two or more books, the random text you generate will blend the vocabulary and phrases from the sources in interesting ways.

Data structures[edit]

Using Markov analysis to generate random text is fun, but there isalso a point to this exercise: data structure selection. In yoursolution to the previous exercises, you had to choose:

  • How to represent the prefixes.
  • How to represent the collection of possible suffixes.
  • How to represent the mapping from each prefix to the collection of possible suffixes.

Ok, the last one is the easy; the only mapping type we haveseen is a dictionary, so it is the natural choice.

For the prefixes, the most obvious options are string,list of strings, or tuple of strings. For the suffixes,one option is a list; another is a histogram (dictionary).

How should you choose? The first step is to think aboutthe operations you will need to implement for each data structure.For the prefixes, we need to be able to remove words fromthe beginning and add to the end. For example, if the currentprefix is “Half a,” and the next word is “bee,” you needto be able to form the next prefix, “a bee.”

Your first choice might be a list, since it is easy to addand remove elements, but we also need to be able to use theprefixes as keys in a dictionary, so that rules out lists.With tuples, you can’t append or remove, but you can usethe addition operator to form a new tuple:

shift takes a tuple of words, prefix, and a string, word, and forms a new tuple that has all the wordsin prefix except the first, and word added tothe end.

For the collection of suffixes, the operations we need toperform include adding a new suffix (or increasing the frequencyof an existing one), and choosing a random suffix.

Adding a new suffix is equally easy for the list implementationor the histogram. Choosing a random element from a listis easy; choosing from a histogram is harder to doefficiently (see Exercise 13.7).

So far we have been talking mostly about ease of implementation,but there are other factors to consider in choosing data structures.One is run time. Sometimes there is a theoretical reason to expectone data structure to be faster than other; for example, I mentionedthat the in operator is faster for dictionaries than for lists,at least when the number of elements is large.

But often you don’t know ahead of time which implementation willbe faster. One option is to implement both of them and see whichis better. This approach is called benchmarking. A practicalalternative is to choose the data structure that iseasiest to implement, and then see if it is fast enough for theintended application. If so, there is no need to go on. If not,there are tools, like the profile module, that can identifythe places in a program that take the most time.

The other factor to consider is storage space. For example, using ahistogram for the collection of suffixes might take less space becauseyou only have to store each word once, no matter how many times itappears in the text. In some cases, saving space can also make yourprogram run faster, and in the extreme, your program might not run atall if you run out of memory. But for many applications, space is asecondary consideration after run time.

One final thought: in this discussion, I have implied thatwe should use one data structure for both analysis and generation. Butsince these are separate phases, it would also be possible to use onestructure for analysis and then convert to another structure forgeneration. This would be a net win if the time saved duringgeneration exceeded the time spent in conversion.

Debugging[edit]

When you are debugging a program, and especially if you areworking on a hard bug, there are four things to try:

reading:
Examine your code, read it back to yourself, andcheck that it says what you meant to say.
running:
Experiment by making changes and running differentversions. Often if you display the right thing at the right placein the program, the problem becomes obvious, but sometimes you have tospend some time to build scaffolding.
ruminating:
Take some time to think! What kind of erroris it: syntax, runtime, semantic? What information can you get fromthe error messages, or from the output of the program? What kind oferror could cause the problem you’re seeing? What did you changelast, before the problem appeared?
retreating:
At some point, the best thing to do is backoff, undoing recent changes, until you get back to a program thatworks and that you understand. Then you can starting rebuilding.

Beginning programmers sometimes get stuck on one of these activitiesand forget the others. Each activity comes with its own failuremode.

For example, reading your code might help if the problem is atypographical error, but not if the problem is a conceptualmisunderstanding. If you don’t understand what your program does, youcan read it 100 times and never see the error, because the error is inyour head.

Running experiments can help, especially if you run small, simpletests. But if you run experiments without thinking or reading yourcode, you might fall into a pattern I call “random walk programming,”which is the process of making random changes until the programdoes the right thing. Needless to say, random walk programmingcan take a long time.

You have to take time to think. Debugging is like anexperimental science. You should have at least one hypothesis aboutwhat the problem is. If there are two or more possibilities, try tothink of a test that would eliminate one of them.

Taking a break helps with the thinking. So does talking.If you explain the problem to someone else (or even yourself), youwill sometimes find the answer before you finish asking the question.

But even the best debugging techniques will fail if there are too manyerrors, or if the code you are trying to fix is too big andcomplicated. Sometimes the best option is to retreat, simplifying theprogram until you get to something that works and that youunderstand.

Beginning programmers are often reluctant to retreat becausethey can’t stand to delete a line of code (even if it’s wrong).If it makes you feel better, copy your program into another filebefore you start stripping it down. Then you can paste the piecesback in a little bit at a time.

Finding a hard bug requires reading, running, ruminating, andsometimes retreating. If you get stuck on one of these activities,try the others.

Glossary[edit]

deterministic:
Pertaining to a program that does the samething each time it runs, given the same inputs.
pseudorandom:
Pertaining to a sequence of numbers that appearto be random, but are generated by a deterministic program.
default value:
The value given to an optional parameter if noargument is provided.
override:
To replace a default value with an argument.
benchmarking:
The process of choosing between data structuresby implementing alternatives and testing them on a sample of thepossible inputs.

Exercises[edit]

Exercise 9[edit]

The “rank” of a word is its position in a list of wordssorted by frequency: the most common word has rank 1, thesecond most common has rank 2, etc.

Zipf’s law describes a relationship between the ranks and frequenciesof words in natural languages1. Specifically, itpredicts that the frequency, 'f', of the word with rank 'r' is:

'f = cr's'

where 's' and 'c' are parameters that depend on the language and thetext. If you take the logarithm of both sides of this equation, youget:

log'f = 'log'cs 'log'r

So if you plot 'log'f' versus 'log'r', you should geta straight line with slope 's' and intercept 'log'c'.

Write a program that reads a text from a file, countsword frequencies, and prints one linefor each word, in descending order of frequency, with'log'f' and 'log'r'. Use the graphing program of yourchoice to plot the results and check whether they forma straight line. Can you estimate the value of 's'?

Notes[edit]

1
Seewikipedia.org/wiki/Zipf's_law
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Persistence[edit]

Most of the programs we have seen so far are transient in thesense that they run for a short time and produce some output,but when they end, their data disappears. If you run the programagain, it starts with a clean slate.

Other programs are persistent: they run for a long time(or all the time); they keep at least some of their datain permanent storage (a hard drive, for example); andif they shut down and restart, they pick up where they left off.

Examples of persistent programs are operating systems, whichrun pretty much whenever a computer is on, and web servers,which run all the time, waiting for requests to come in onthe network.

One of the simplest ways for programs to maintain their datais by reading and writing text files. We have already seenprograms that read text files; in this chapters we will see programsthat write them.

An alternative is to store the state of the program in a database.In this chapter I will present a simple database and a module,pickle, that makes it easy to store program data.

Reading and writing[edit]

A text file is a sequence of characters stored on a permanentmedium like a hard drive, flash memory, or CD-ROM. We saw howto open and read a file in Section 9.1.

To write a file, you have to open it with mode'w' as a second parameter:

If the file already exists, opening it in write mode clears outthe old data and starts fresh, so be careful!If the file doesn’t exist, a new one is created.

The write method puts data into the file.

Again, the file object keeps track of where it is, so ifyou call write again, it adds the new data to the end.

When you are done writing, you have to close the file.

Format operator[edit]

The argument of write has to be a string, so if we wantto put other values in a file, we have to convert them tostrings. The easiest way to do that is with str:

An alternative is to use the format operator, %. Whenapplied to integers, % is the modulus operator. Butwhen the first operand is a string, % is the format operator.

The first operand is the format string, and the second operandis a tuple of expressions. The result is a string that containsthe values of the expressions, formatted according to the formatstring.

As an example, the format sequence'%d' means thatthe first expression in the tuple should be formatted as aninteger (d stands for “decimal”):

The result is the string '42', which is not to be confusedwith the integer value 42.

A format sequence can appear anywhere in the format string,so you can embed a value in a sentence:

The format sequence '%g' formats the next element in the tupleas a floating-point number (don’t ask why), and '%s' formatsthe next item as a string:

The number of elements in the tuple has to match the numberof format sequences in the string. Also, the types of theelements have to match the format sequences:

In the first example, there aren’t enough elements; in thesecond, the element is the wrong type.

The format operator is powerful but difficult to use. You canread more about it at docs.python.org/lib/typesseq-strings.html.

Filenames and paths[edit]

Files are organized into directories (also called “folders”).Every running program has a “current directory,” which is thedefault directory for most operations. For example, when you open a file for reading, Python looks for it in thecurrent directory.

The os module provides functions for working with files anddirectories (“os” stands for “operating system”). os.getcwdreturns the name of the current directory:

cwd stands for “current working directory.” The result inthis example is /home/dinsdale, which is the home directory of auser named dinsdale.

A string like cwd that identifies a file is called a path.A relative path starts from the current directory;an absolute path starts from the topmost directory in thefile system.

The paths we have seen so far are simple filenames, so they arerelative to the current directory. To find the absolute path toa file, you can use os.path.abspath:

os.path.exists checkswhether a file or directory exists:

If it exists, os.path.isdir checks whether it’s a directory:

Similarly, os.path.isfile checks whether it’s a file.

os.listdir returns a list of the files (and other directories)in the given directory:

To demonstrate these functions, the following example“walks” through a directory, printsthe names of all the files, and calls itself recursively onall the directories.

os.path.join takes a directory and a file name and joinsthem into a complete path.

Exercise 1[edit]

Modify 'walk' so that instead of printing the names ofthe files, it returns a list of names.

Exercise 2

The 'os' module provides a function called 'walk'that is similar to this one but more versatile. Readthe documentation and use it to print the names of thefiles in a given directory and its subdirectories.

Catching exceptions[edit]

A lot of things can go wrong when you try to read and writefiles. If you try to open a file that doesn’t exist, you get anIOError:

If you don’t have permission to access a file:

And if you try to open a directory for reading, you get

To avoid these errors, you could use functions like os.path.existsand os.path.isfile, but it would take a lot of time and codeto check all the possibilities (if “Errno 21” is anyindication, there are at least 21 things that can go wrong).

It is better to go ahead and try, and deal with problems if theyhappen, which is exactly what the try statement does. Thesyntax is similar to an if statement:

Python starts by executing the try clause. If all goeswell, it skips the except clause and proceeds. If anexception occurs, it jumps out of the try clause andexecutes the except clause.

Handling an exception with a try statement is called catching an exception. In this example, the except clauseprints an error message that is not very helpful. In general,catching an exception gives you a chance to fix the problem, or tryagain, or at least end the program gracefully.

Databases[edit]

A database is a file that is organized for storing data.Most databases are organized like a dictionary in the sensethat they map from keys to values. The biggest differenceis that the database is on disk (or other permanent storage),so it persists after the program ends.

The module anydbm provides an interface for creatingand updating database files. As an example, I’ll create a databasethat contains captions for image files.

Opening a database is similarto opening other files:

The mode 'c' means that the database should be created ifit doesn’t already exist. The result is a database objectthat can be used (for most operations) like a dictionary.If you create a new item, anydbm updates the database file.

When you access one of the items, anydbm reads the file:

If you make another assignment to an existing key, anydbm replacesthe old value:

Many dictionary methods, like keys and items, alsowork with database objects. So does iteration with a forstatement.

As with other files, you should close the database when you aredone:

Pickling[edit]

A limitation of anydbm is that the keys and values haveto be strings. If you try to use any other type, you get anerror.

The pickle module can help. It translatesalmost any type of object into a string suitable for storage in adatabase, and then translates strings back into objects.

pickle.dumps takes an object as a parameter and returnsa string representation (dumps is short for “dump string”):

The format isn’t obvious to human readers; it is meant to beeasy for pickle to interpret. pickle.loads(“load string”) reconstitutes the object:

Although the new object has the same value as the old, it isnot (in general) the same object:

In other words, pickling and then unpickling has the same effectas copying the object.

You can use pickle to store non-strings in a database.In fact, this combination is so common that it has beenencapsulated in a module called shelve.

Exercise 3

If you did Exercise '12.4', modify your solution so thatit creates a database that maps from each word in the list toa list of words that use the same set of letters.

Write a different program that opens the database and printsthe contents in a human-readable format.

Pipes[edit]

Most operating systems provide a command-line interface,also known as a shell. Shells usually provide commandsto navigate the file system and launch applications. Forexample, in Unix, you can change directories with cd,display the contents of a directory with ls, and launcha web browser by typing (for example) firefox.

Any program that you can launch from the shell can also belaunched from Python using a pipe. A pipe is an objectthat represents a running process.

For example, the Unix command ls -l normally displays thecontents of the current directory (in long format). You canlaunch ls with os.popen:

The argument is a string that contains a shell command. Thereturn value is a file pointer that behaves just like an openfile. You can read the output from the ls process oneline at a time with readline or get the whole thing atonce with read:

When you are done, you close the pipe like a file:

The return value is the final status of the ls process;None means that it ended normally (with no errors).

A common use of pipes is to read a compressed file incrementally;that is, without uncompressing the whole thing at once. Thefollowing function takes the name of a compressed file as aparameter and returns a pipe that uses gzip to decompressthe contents:

If you read lines from fp one at a time, you never haveto store the uncompressed file in memory or on disk.

Writing modules[edit]

Any file that contains Python code can be imported as a module.For example, suppose you have a file named wc.py with the followingcode:

If you run this program, it reads itself and prints the numberof lines in the file, which is 7.You can also import it like this:

Now you have a module object wc:

That provides a function called linecount:

So that’s how you write modules in Python.

The only problem with this example is that when you importthe module it executes the test code at the bottom. Normallywhen you import a module, it defines new functions but itdoesn’t execute them.

Programs that will be imported as modules oftenuse the following idiom:

__name__ is a built-in variable that is set when theprogram starts. If the program is running as a script,__name__ has the value __main__; in thatcase, the test code is executed. Otherwise,if the module is being imported, the test code is skipped.

Exercise 4

Type this example into a file named 'wc.py' and runit as a script. Then run the Python interpreter and'import wc'. What is the value of __name__when the module is being imported?Warning: If you import a module that has already been imported,Python does nothing. It does not re-read the file, even if it haschanged.

If you want to reload a module, you can use the built-in function 'reload', but it can be tricky, so the safest thing to do isrestart the interpreter and then import the module again.

Debugging[edit]

When you are reading and writing files, you might run into problemswith whitespace. These errors can be hard to debug because spaces,tabs and newlines are normally invisible:

The built-in function repr can help. It takes any object as anargument and returns a string representation of the object. Forstrings, it represents whitespacecharacters with backslash sequences:

This can be helpful for debugging.

One other problem you might run into is that different systemsuse different characters to indicate the end of a line. Somesystems use a newline, represented n. Others usea return character, represented r. Some use both.If you move files between different systems, these inconsistenciesmight cause problems.

For most systems, there are applications to convert from oneformat to another. You can find them (and read more about thisissue) at wikipedia.org/wiki/Newline. Or, of course, youcould write one yourself.

Glossary[edit]

persistent:
Pertaining to a program that runs indefinitelyand keeps at least some of its data in permanent storage.
format operator:
An operator, %, that takes a formatstring and a tuple and generates a string that includesthe elements of the tuple formatted as specified by the format string.
format string:
A string, used with the format operator, thatcontains format sequences.
format sequence:
A sequence of characters in a format string,like %d, that specifies how a value should be formatted.
text file:
A sequence of characters stored in permanentstorage like a hard drive.
directory:
A named collection of files, also called a folder.
path:
A string that identifies a file.
relative path:
A path that starts from the current directory.
absolute path:
A path that starts from the topmost directoryin the file system.
catch:
To prevent an exception from terminatinga program using the tryand except statements.
database:
A file whose contents are organized like a dictionarywith keys that correspond to values.

Exercises[edit]

Exercise 5

The 'urllib' module provides methods for manipulating URLsand downloading information from the web. The following exampledownloads and prints a secret message from 'thinkpython.com':

Run this code and follow the instructions you see there.

Exercise 6

In a large collection of MP3 files, there may be more than onecopy of the same song, stored in different directories or withdifferent file names. The goal of this exercise is to search forthese duplicates.

  • Write a program that searches a directory and all of its

subdirectories, recursively, and returns a list of complete pathsfor all files with a given suffix (like '.mp3').Hint: 'os.path' provides several useful functions formanipulating file and path names.

  • To recognize duplicates, you can use a hash function that

reads the file and generates a short summaryof the contents. For example,MD5 (Message-Digest algorithm 5) takes an arbitrarily-long“message” and returns a 128-bit “checksum.” The probabilityis very small that two files with different contents willreturn the same checksum.You can read about MD5 at 'wikipedia.org/wiki/Md5'. Ona Unix system you can use the program 'md5sum' and a pipe tocompute checksums from Python.

Exercise 7

'

The Internet Movie Database (IMDb) is an online collection ofinformation about movies. Their database is availablein plain text format, so it is reasonably easy to read fromPython. For this exercise, the files you needare 'actors.list.gz' and 'actresses.list.gz'; youcan download them from 'www.imdb.com/interfaces#plain'.

'

I have written a program that parses these files andsplits them into actor names, movie titles, etc. You candownload it from 'thinkpython.com/code/imdb.py'.

If you run 'imdb.py' as a script, it reads 'actors.list.gz'and prints one actor-movie pair per line. Or, if you 'importimdb' you can use the function process_file to, well,process the file. The arguments are a filename, a functionobject and an optional number of lines to process. Here isan example:

When you call process_file, it opens 'filename', reads thecontents, and calls print_info once for each line in the file.print_info takes an actor, date, movie title and role asarguments and prints them.

  • Write a program that reads 'actors.list.gz' and 'actresses.list.gz' and uses 'shelve' to build a database

that maps from each actor to a list of his or her films.

  • Two actors are “costars” if they have been in at least one

movie together. Process the database you built in the previous stepand build a second database that maps from each actor to a list ofhis or her costars.

  • Write a program that can play the “Six Degrees of Kevin

Bacon,” which you can read about at'wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon'. Thisproblem is challenging because it requires you to find the shortestpath in a graph. You can read about shortest path algorithmsat 'wikipedia.org/wiki/Shortest_path_problem'.

A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

User-defined types[edit]

We have used many of Python’s built-in types; now we are goingto define a new type. As an example, we will create a typecalled Point that represents a point in two-dimensionalspace.

In mathematical notation, points are often written inparentheses with a comma separating the coordinates. For example,(0, 0) represents the origin, and (x, y) represents thepoint x units to the right and y units up from the origin.

There are several ways we might represent points in Python:

  • We could store the coordinates separately in two variables, x and y.
  • We could store the coordinates as elements in a list or tuple.
  • We could create a new type to represent points as objects.

Creating a new typeis (a little) more complicated than the other options, butit has advantages that will be apparent soon.

A user-defined type is also called a class.A class definition looks like this:

This header indicates that the new class is a Point,which is a kind of object, which is a built-intype.

The body is a docstring that explains what the class is for.You can define variables and functions inside a class definition,but we will get back to that later.

Defining a class named Point creates a class object.

Because Point is defined at the top level, its “fullname” is __main__.Point.

The class object is like a factory for creating objects. To create aPoint, you call Point as if it were a function.

The return value is a reference to a Point object, which weassign to blank. Creating a new object is calledinstantiation, and the object is an instance ofthe class.

When you print an instance, Python tells you what class itbelongs to and where it is stored in memory (the prefix0x means that the following number is in hexadecimal).

Attributes[edit]

You can assign values to an instance using dot notation:

This syntax is similar to the syntax for selecting a variable from amodule, such as math.pi or string.whitespace. In this case,though, we are assigning values to named elements of an object.These elements are called attributes.

As a noun, “AT-trib-ute” is pronounced with emphasis on the firstsyllable, as opposed to “a-TRIB-ute,” which is a verb.

The following diagram shows the result of these assignments.A state diagram that shows an object and its attributes iscalled an object diagram:

The variable blank refers to a Point object, whichcontains two attributes. Each attribute refers to afloating-point number.

You can read the value of an attribute using the same syntax:

The expression blank.x means, “Go to the object blankrefers to and get the value of x.” In this case, we assign thatvalue to a variable named x. There is no conflict betweenthe variable x and the attribute x.

You can use dot notation as part of any expression. For example:

You can pass an instance as an argument in the usual way.For example:

print_point takes a point as an argument and displays it inmathematical notation. To invoke it, you can pass blank asan argument:

Inside the function, p is an alias for blank, so ifthe function modifies p, blank changes.

Exercise 1[edit]

Write a function called 'distance' that it takes two Pointsas arguments and returns the distance between them.

Rectangles[edit]

Sometimes it is obvious what the attributes of an object should be,but other times you have to make decisions. For example, imagine youare designing a class to represent rectangles. What attributes wouldyou use to specify the location and size of a rectangle? You canignore angle; to keep things simple, assume that the rectangle iseither vertical or horizontal.

There are at least two possibilities:

  • You could specify one corner of the rectangle (or the center), the width, and the height.
  • You could specify two opposing corners.

At this point it is hard to say whether either is better thanthe other, so we’ll implement the first one, just as an example.

Here is the class definition:

The docstring lists the attributes: width andheight are numbers; corner is a Point object thatspecifies the lower-left corner.

To represent a rectangle, you have to instantiate a Rectangleobject and assign values to the attributes:

The expression box.corner.x means,“Go to the object box refers to and select the attribute namedcorner; then go to that object and select the attribute namedx.”

The figure shows the state of this object:

File:Book023.pngAn object that is an attribute of another object is embedded.

Instances as return values[edit]

Functions can return instances. For example, find_centertakes a Rectangle as an argument and returns a Pointthat contains the coordinates of the center of the Rectangle:

Here is an example that passes box as an argument and assignsthe resulting Point to center:

Objects are mutable[edit]

You can change the state of an object by making an assignment to one ofits attributes. For example, to change the size of a rectanglewithout changing its position, you can modify the values of width and height:

You can also write functions that modify objects. For example,grow_rectangle takes a Rectangle object and two numbers,dwidth and dheight, and adds the numbers to thewidth and height of the rectangle:

Here is an example that demonstrates the effect:

Inside the function, rect is analias for box, so if the function modifies rect, box changes.

Exercise 2[edit]

Write a function named move_rectangle that takesa Rectangle and two numbers named 'dx' and 'dy'. Itshould change the location of the rectangle by adding 'dx'to the 'x' coordinate of 'corner' and adding 'dy'to the 'y' coordinate of 'corner'.

Copying[edit]

Aliasing can make a program difficult to read because changesin one place might have unexpected effects in another place.It is hard to keep track of all the variables that might referto a given object.

Copying an object is often an alternative to aliasing.The copy module contains a function called copy thatcan duplicate any object:

p1 and p2 contain the same data, but they arenot the same Point.

The is operator indicates that p1 and p2 are not thesame object, which is what we expected. But you might have expected to yield True because these points contain the samedata. In that case, you will be disappointed to learn that forinstances, the default behavior of the operator is the sameas the is operator; it checks object identity, not objectequivalence. This behavior can be changed—we’ll see how later.

If you use copy.copy to duplicate a Rectangle, you will findthat it copies the Rectangle object but not the embedded Point.

Here is what the object diagram looks like:

<IMG SRC='book024.png'>

This operation is called a shallow copy because it copies theobject and any references it contains, but not the embedded objects.

For most applications, this is not what you want. In this example,invoking grow_rectangle on one of the Rectangles would notaffect the other, but invoking move_rectangle on either wouldaffect both! This behavior is confusing and error-prone.

Fortunately, the copy module contains a method named deepcopy that copies not only the object but also the objects it refers to, and the objects they refer to,and so on.You will not be surprised to learn that this operation iscalled a deep copy.

box3 and box are completely separate objects.

Exercise 3[edit]

Write a version of move_rectangle that creates andreturns a new Rectangle instead of modifying the old one.

Debugging[edit]

When you start working with objects, you are likely to encountersome new exceptions. If you try to access an attributethat doesn’t exist, you get an AttributeError:

If you are not sure what type an object is, you can ask:

If you are not sure whether an object has a particular attribute,you can use the built-in function hasattr:

The first argument can be any object; the second argument is a string that contains the name of the attribute.

Glossary[edit]

class:
A user-defined type. A class definition creates a newclass object.
class object:
An object that contains information about auser-defined type. The class object can be used to create instancesof the type.
instance:
An object that belongs to a class.
attribute:
One of the named values associated with an object.
embedded (object):
An object that is stored as an attributeof another object.
shallow copy:
To copy the contents of an object, includingany references to embedded objects;implemented by the copy function in the copy module.
deep copy:
To copy the contents of an object as well as anyembedded objects, and any objects embedded in them, and so on;implemented by the deepcopy function in the copy module.
object diagram:
A diagram that shows objects, theirattributes, and the values of the attributes.

Exercises[edit]

Exercise 4[edit]

World.py', which is part of Swampy (see Chapter '4'),contains a class definition for a user-defined type called 'World'. If you run this code:

A window should appear with a title bar and an empty square.In this exercise we will use this window to draw Points,Rectangles and other shapes. Add the following lines beforewait_for_user and run the program again

You should see a green rectangle with a black outline.The first line creates a Canvas, which appears in the windowas a white square. The Canvas object provides methods like'rectangle' for drawing various shapes.

bbox' is a list of lists that represents the “bounding box”of the rectangle. The first pair of coordinates is the lower-leftcorner of the rectangle; the second pair is the upper-right corner.

You can draw a circle like this:

The first parameter is the coordinate pair for the center of thecircle; the second parameter is the radius.

If you add this line to the program, the result should resemble the national flag of Bangladesh(see 'wikipedia.org/wiki/Gallery_of_sovereign-state_flags').

  • Write a function called draw_rectangle that takes a

Canvas and a Rectangle as arguments and draws arepresentation of the Rectangle on the Canvas.

  • Add an attribute named 'color' to your Rectangle objects and

modify draw_rectangle so that it uses the color attribute asthe fill color.

  • Write a function called draw_point that takes a

Canvas and a Point as arguments and draws arepresentation of the Point on the Canvas.

  • Define a new class called Circle with appropriate attributes and

instantiate a few Circle objects. Write a function calleddraw_circle that draws circles on the canvas.

  • Write a program that draws the national flag of of the Czech Republic.
Hint: you can draw a polygon like this:

I have written a small program that lists the available colors;you can download it from 'thinkpython.com/code/color_list.py'.

A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Time[edit]

As another example of a user-defined type, we'll define a class calledTime that records the time of day. The class definition lookslike this:

We can create a new Time object and assignattributes for hours, minutes, and seconds:

The state diagram for the Time object looks like this:


<IMG SRC='book025.png'>

Exercise 1[edit]

Write a function called print_time that takes a Time object and prints it in the form hour:minute:second.

Hint: the format sequence %.2d prints an integer usingat least two digits, including a leading zero if necessary.

Exercise 2[edit]

Write a boolean function called is_after thattakes two Time objects, t1 and t2, andreturns True if t1 follows t2chronologically and False otherwise.

Challenge: don't use an if statement.

Pure functions[edit]

In the next few sections, we’ll write two functions that add timevalues. They demonstrate two kinds of functions: pure functions andmodifiers. They also demonstrate a development plan I’ll call prototype and patch, which is a way of tackling a complex problemby starting with a simple prototype and incrementally dealing with thecomplications.

Here is a simple prototype of add_time:

The function creates a new Time object, initializes itsattributes, and returns a reference to the new object. This is calleda pure function because it does not modify any of the objectspassed to it as arguments and it has no effect,like displaying a value or getting user input, other than returning a value.

To test this function, I’ll create two Time objects: startcontains the start time of a movie, like Monty Python and theHoly Grail, and duration contains the run time of the movie,which is one hour 35 minutes.

add_time figures out when the movie will be done.

The result, 10:80:00 might not be what you were hopingfor. The problem is that this function does not deal with cases where thenumber of seconds or minutes adds up to more than sixty. When thathappens, we have to “carry” the extra seconds into the minute columnor the extra minutes into the hour column.

Here’s an improved version:

Although this function is correct, it is starting to get big.We will see a shorter alternative later.

Modifiers[edit]

Sometimes it is useful for a function to modify the objects it gets asparameters. In that case, the changes are visible to the caller.Functions that work this way are called modifiers.

increment, which adds a given number of seconds to a Timeobject, can be written naturally as amodifier. Here is a rough draft:

The first line performs the basic operation; the remainder dealswith the special cases we saw before.

Is this function correct? What happens if the parameter secondsis much greater than sixty?

In that case, it is not enough to carryonce; we have to keep doing it until time.second is less than sixty.One solution is to replace the if statements with whilestatements. That would make the function correct, but notvery efficient.

Exercise 3

Write a correct version of 'increment' thatdoesn’t contain any loops.

Anything that can be done with modifiers can also be done with purefunctions. In fact, some programming languages only allow purefunctions. There is some evidence that programs that use purefunctions are faster to develop and less error-prone than programsthat use modifiers. But modifiers are convenient at times,and functional programs tend to be less efficient.

In general, I recommend that you write pure functions whenever it isreasonable and resort to modifiers only if there is a compellingadvantage. This approach might be called a functionalprogramming style.

Exercise 4

Write a “pure” version of 'increment' that creates and returnsa new Time object rather than modifying the parameter.

Prototyping versus planning[edit]

The development plan I am demonstrating is called “prototype andpatch.” For each function, I wrote a prototype that performed thebasic calculation and then tested it, patching errors along theway.

This approach can be effective, especially if you don’t yet have adeep understanding of the problem. But incremental corrections cangenerate code that is unnecessarily complicated—since it deals withmany special cases—and unreliable—since it is hard to know if youhave found all the errors.

An alternative is planned development, in which high-levelinsight into the problem can make the programming much easier. Inthis case, the insight is that a Time object is really a three-digitnumber in base 60 (see wikipedia.org/wiki/Sexagesimal)! Thesecond attribute is the “ones column,” the minuteattribute is the “sixties column,” and the hour attribute isthe “thirty-six hundreds column.”

When we wrote add_time and increment, we were effectivelydoing addition in base 60, which is why we had to carry from onecolumn to the next.

This observation suggests another approach to the whole problem—wecan convert Time objects to integers and take advantage of the factthat the computer knows how to do integer arithmetic.

Here is a function that converts Times to integers:

And here is the function that converts integers to Times(recall that divmod divides the first argument by the secondand returns the quotient and remainder as a tuple).

You might have to think a bit, and run some tests, to convinceyourself that these functions are correct. One way to test them is tocheck that time_to_int(int_to_time(x)) x for many values ofx. This is an example of a consistency check.

Once you are convinced they are correct, you can use them to rewrite add_time:

This version is shorter than the original, and easier to verify.

Exercise 5

Rewrite 'increment' using time_to_int and int_to_time.

In some ways, converting from base 60 to base 10 and back is harderthan just dealing with times. Base conversion is more abstract; ourintuition for dealing with time values is better.

But if we have the insight to treat times as base 60 numbers and makethe investment of writing the conversion functions (time_to_intand int_to_time), we get a program that is shorter, easier toread and debug, and more reliable.

It is also easier to add features later. For example, imaginesubtracting two Times to find the duration between them. Thenaïve approach would be to implement subtraction with borrowing.Using the conversion functions would be easier and more likely to becorrect.

Ironically, sometimes making a problem harder (or more general) makes iteasier (because there are fewer special cases and fewer opportunitiesfor error).

Debugging[edit]

A Time object is well-formed if the values of minutes and seconds are between 0 and 60 (including 0 but not 60) and if hours is positive. hours and minutes should beintegral values, but we might allow seconds to have afraction part.

These kind of requirements are called invariants becausethey should always be true. To put it a different way, if theyare not true, then something has gone wrong.

Writing code to check your invariants can help you detect errorsand find their causes. For example, you might have a functionlike valid_time that takes a Time object and returnsFalse if it violates an invariant:

Then at the beginning of each function you could check thearguments to make sure they are valid:


Or you could use an assert statement, which checks a given invariantand raises an exception if it fails:


assert statements are useful because they distinguishcode that deals with normal conditions from codethat checks for errors.

Glossary[edit]

prototype and patch:
A development plan that involveswriting a rough draft of a program, testing, and correcting errors asthey are found.
planned development:
A development plan that involveshigh-level insight into the problem and more planning than incrementaldevelopment or prototype development.
pure function:
A function that does not modify any of the objects itreceives as arguments. Most pure functions are fruitful.
modifier:
A function that changes one or more of the objects itreceives as arguments. Most modifiers are fruitless.
functional programming style:
A style of program design in which themajority of functions are pure.
invariant:
A condition that should always be true during theexecution of a program.

Exercises[edit]

Exercise 6[edit]

Write a function called mul_time that takes a Time objectand a number and returns a new Time object that containsthe product of the original Time and the number.Then use mul_time to write a function that takes a Timeobject that represents the finishing time in a race, and a numberthat represents the distance, and returns a Time object that representsthe average pace (time per mile).

Exercise 7[edit]

Write a class definition for a Date object that has attributes 'day', 'month' and 'year'. Write a function calledincrement_date that takes a Date object, 'date' and aninteger, 'n', and returns a new Date object thatrepresents the day 'n' days after 'date'. Hint:“Thirty days hath September...” Challenge: does your functiondeal with leap years correctly? See 'wikipedia.org/wiki/Leap_year

Exercise 8[edit]

The 'datetime' module provides 'date' and 'time' objectsthat are similar to the Date and Time objects in this chapter, butthey provide a rich set of methods and operators. Read thedocumentation at 'docs.python.org/lib/datetime-date.html'.

  • Use the 'datetime' module to write a program that gets the current date and prints the day of the week.
  • Write a program that takes a birthday as input and prints the user’s age and the number of days, hours, minutes and seconds until their next birthday.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Object-oriented features[edit]

Python is an object-oriented programming language, which meansthat it provides features that support object-orientedprogramming.

It is not easy to define object-oriented programming, but we havealready seen some of its characteristics:

  • Programs are made up of object definitions and function definitions, and most of the computation is expressed in terms of operations on objects.
  • Each object definition corresponds to some object or concept in the real world, and the functions that operate on that object correspond to the ways real-world objects interact.

For example, the Time class defined in Chapter 16corresponds to the way people record the time of day, and thefunctions we defined correspond to the kinds of things people do withtimes. Similarly, the Point and Rectangle classescorrespond to the mathematical concepts of a point and a rectangle.

So far, we have not taken advantage of the features Python provides tosupport object-oriented programming. Thesefeatures are not strictly necessary; most of them providealternative syntax for things we have already done. But in many cases,the alternative is more concise and more accurately conveys thestructure of the program.

For example, in the Time program, there is no obviousconnection between the class definition and the function definitionsthat follow. With some examination, it is apparent that every functiontakes at least one Time object as an argument.

This observation is the motivation for methods; a method isa function that is associated with a particular class.We have seen methods for strings, lists, dictionaries and tuples.In this chapter, we will define methods for user-defined types.

Methods are semantically the same as functions, but there aretwo syntactic differences:

  • Methods are defined inside a class definition in order to make the relationship between the class and the method explicit.
  • The syntax for invoking a method is different from the syntax for calling a function.

In the next few sections, we will take the functions from the previoustwo chapters and transform them into methods. This transformation ispurely mechanical; you can do it simply by following a sequence ofsteps. If you are comfortable converting from one form to another,you will be able to choose the best form for whatever you are doing.

Printing objects[edit]

In Chapter 16, we defined a class namedTime and in Exercise 16.1, you wrote a function named print_time:

To call this function, you have to pass a Time object as anargument:

To make print_time a method, all we have to do ismove the function definition inside the class definition. Noticethe change in indentation.

Now there are two ways to call print_time. The first(and less common) way is to use function syntax:

In this use of dot notation, Time is the name of the class,and print_time is the name of the method. start ispassed as a parameter.

The second (and more concise) way is to use method syntax:

In this use of dot notation, print_time is the name of themethod (again), and start is the object the method isinvoked on, which is called the subject. Just as thesubject of a sentence is what the sentence is about, the subjectof a method invocation is what the method is about.

Inside the method, the subject is assigned to the firstparameter, so in this case start is assignedto time.

By convention, the first parameter of a method iscalled self, so it would be more common to writeprint_time like this:

The reason for this convention is an implicit metaphor:

  • The syntax for a function call, print_time(start),

suggests that the function is the active agent. It says somethinglike, “Hey print_time! Here’s an object for you to print.”

  • In object-oriented programming, the objects are the active agents.

A method invocation like start.print_time() says“Hey start! Please print yourself.”

This change in perspective might be more polite, but it is not obviousthat it is useful. In the examples we have seen so far, it may notbe. But sometimes shifting responsibility from the functions onto theobjects makes it possible to write more versatile functions, and makesit easier to maintain and reuse code.

Exercise 1[edit]

Rewrite time_to_int(from Section '16.4') as a method. It is probably notappropriate to rewrite int_to_time as a method; it’s notclear what object you would invoke it on!

Another example[edit]

Here’s a version of increment (from Section 16.3)rewritten as a method:

This version assumes that time_to_int is writtenas a method, as in Exercise 17.1. Also, note thatit is a pure function, not a modifier.

Here’s how you would invoke increment:

The subject, start, gets assigned to the first parameter,self. The argument, 1337, gets assigned to thesecond parameter, seconds.

This mechanism can be confusing, especially if you make an error.For example, if you invoke increment with two arguments, youget:

The error message is initially confusing, because there areonly two arguments in parentheses. But the subject is alsoconsidered an argument, so all together that’s three.

A more complicated example[edit]

is_after (from Exercise 16.2) is slightly more complicatedbecause it takes two Time objects as parameters. In this case it isconventional to name the first parameter self and the secondparameter other:

To use this method, you have to invoke it on one object and passthe other as an argument:

One nice thing about this syntax is that it almost readslike English: “end is after start?”

The init method[edit]

The init method (short for “initialization”) isa special method that gets invoked when an object is instantiated. Its full name is __init__ (two underscore characters,followed by init, and then two more underscores). Aninit method for the Time class might look like this:

It is common for the parameters of __init__to have the same names as the attributes. The statement

stores the value of the parameter hour as an attributeof self.

The parameters are optional, so if you call Time withno arguments, you get the default values.

If you provide one argument, it overrides hour:

If you provide two arguments, they override hour andminute.

And if you provide three arguments, they override all threedefault values.

Exercise 2[edit]

Write an init method for the 'Point' class that takes'x' and 'y' as optional parameters and assignsthem to the corresponding attributes.

The __str__ method[edit]

__str__ is a special method, like __init__,that is supposed to return a string representation of an object.

For example, here is a str method for Time objects:

When you print an object, Python invokes the str method:

When I write a new class, I almost always start by writing __init__, which makes it easier to instantiate objects, and __str__, which is useful for debugging.

Exercise 3[edit]

Write a 'str' method for the 'Point' class. Createa Point object and print it.

Operator overloading[edit]

By defining other special methods, you can specify the behaviorof operators on user-defined types. For example, if you definea method named __add__ for the Time class, you can use the+ operator on Time objects.

Here is what the definition might look like:

And here is how you could use it:

When you apply the + operator to Time objects, Python invokes__add__. When you print the result, Python invokes __str__. So there is quite a lot happening behind the scenes!

Changing the behavior of an operator so that it works withuser-defined types is called operator overloading. For everyoperator in Python there is a corresponding special method, like __add__. For more details, seedocs.python.org/ref/specialnames.html.

Exercise 4[edit]

Write an 'add' method for the Point class.

Type-based dispatch[edit]

In the previous section we added two Time objects, but youalso might want to add an integer to a Time object. Thefollowing is a version of __add__that checks the type of other and invokes eitheradd_time or increment:

The built-in function isinstance takes a value and aclass object, and returns True if the value is an instanceof the class.

If other is a Time object, __add__ invokesadd_time. Otherwise it assumes that the parameteris a number and invokes increment. This operation iscalled a type-based dispatch because it dispatches thecomputation to different methods based on the type of thearguments.

Here are examples that use the + operator with differenttypes:

Unfortunately, this implementation of addition is not commutative.If the integer is the first operand, you get

The problem is, instead of asking the Time object to add an integer,Python is asking an integer to add a Time object, and it doesn’t knowhow to do that. But there is a clever solution for this problem: thespecial method __radd__, which stands for “right-side add.”This method is invoked when a Time object appears on the right side ofthe + operator. Here’s the definition:

And here’s how it’s used:

Exercise 5[edit]

Write an 'add' method for Points that works with either aPoint object or a tuple:

  • If the second operand is a Point, the method should return a new Point whose 'x' coordinate is the sum of the 'x' coordinates of the operands, and likewise for the 'y' coordinates.
  • If the second operand is a tuple, the method should add the first element of the tuple to the 'x' coordinate and the second element to the 'y' coordinate, and return a new Point with the result.

Polymorphism[edit]

Type-based dispatch is useful when it is necessary, but (fortunately)it is not always necessary. Often you can avoid it by writing functionsthat work correctly for arguments with different types.

Many of the functions we wrote for strings will actuallywork for any kind of sequence.For example, in Section 11.1we used histogram to count the number of times each letterappears in a word.

This function also works for lists, tuples, and even dictionaries,as long as the elements of s are hashable, so they can be usedas keys in d.

Functions that can work with several types are called polymorphic.Polymorphism can facilitate code reuse. For example, the built-infunction sum, which adds the elements of a sequence, worksas long as the elements of the sequence support addition.

Since Time objects provide an add method, they workwith sum:

In general, if all of the operations inside a function work with a given type, then the function works with that type.

The best kind of polymorphism is the unintentional kind, whereyou discover that a function you already wrote can beapplied to a type you never planned for.

Debugging[edit]

It is legal to add attributes to objects at any point in the executionof a program, but if you are a stickler for type theory, it is adubious practice to have objects of the same type with differentattribute sets. It is usually a good idea toinitialize all of an objects attributes in the init method.

If you are not sure whether an object has a particular attribute, youcan use the built-in function hasattr (see Section 15.7).

Another way to access the attributes of an object is through thespecial attribute __dict__, which is a dictionary that mapsattribute names (as strings) and values:

For purposes of debugging, you might find it useful to keep thisfunction handy:

print_attributes traverses the items in the object’s dictionaryand prints each attribute name and its corresponding value.

The built-in function getattr takes an object and an attributename (as a string) and returns the attribute’s value.

Glossary[edit]

object-oriented language:
A language that provides features,such as user-defined classes and method syntax, that facilitateobject-oriented programming.
object-oriented programming:
A style of programming in whichdata and the operations that manipulate it are organized into classesand methods.
method:
A function that is defined inside a class definition andis invoked on instances of that class.
subject:
The object a method is invoked on.
operator overloading:
Changing the behavior of an operator like+ so it works with a user-defined type.
type-based dispatch:
A programming pattern that checks the typeof an operand and invokes different functions for different types.
polymorphic:
Pertaining to a function that can work with morethan one type.

Exercises[edit]

Exercise 6[edit]

This exercise is a cautionary tale about one of the mostcommon, and difficult to find, errors in Python.

  • Write a definition for a class named 'Kangaroo' with the following

methods:

  • An __init__ method that initializes an attribute named pouch_contents to an empty list.
  • A method named put_in_pouch that takes an object of any type and adds it to pouch_contents.
  • A __str__ method that returns a string representation of the Kangaroo object and the contents of the pouch.

Test your code by creating two ''Kangaroo'' objects, assigning them to variablesnamed ''kanga'' and ''roo'', and then adding ''roo'' to thecontents of ''kanga''’s pouch.'

  • 'Download ''thinkpython.com/code/BadKangaroo.py''. It contains

a solution to the previous problem with one big, nasty bug.Find and fix the bug.'If you get stuck, you can download''thinkpython.com/code/GoodKangaroo.py'', which explains theproblem and demonstrates a solution.'

Exercise 7[edit]

Visual is a Python module that provides 3-D graphics. It isnot always included in a Python installation, so you might haveto install it from your software repository or, if it’s not there,from 'vpython.org'.

The following example creates a 3-D space that is 256 unitswide, long and high, and sets the “center” to be thepoint '(128, 128, 128)'. Then it draws a blue sphere.

color' is an RGB tuple; that is, the elements are Red-Green-Bluelevels between 0.0 and 1.0 (see'wikipedia.org/wiki/RGB_color_model').

If you run this code, you should see a window with a blackbackground and a blue sphere. If you drag the middle buttonup and down, you can zoom in and out. You can also rotatethe scene by dragging the right button, but with only onesphere in the world, it is hard to tell the difference.

The following loop creates a cube of spheres:

  • Put this code in a script and make sure it works for

you.

  • Modify the program so that each sphere in the cube

has the color that corresponds to its position in RGB space.Notice that the coordinates are in the range 0–255, butthe RGB tuples are in the range 0.0–1.0.

  • Download 'thinkpython.com/code/color_list.py'

and use the function read_colors to generate a listof the available colors on your system, their names andRGB values. For each named color draw a sphere in theposition that corresponds to its RGB values.

You can see my solution at 'thinkpython.com/code/color_space.py'.

Further reading[edit]

A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

In this chapter we will develop classes to represent playing cards,decks of cards, and poker hands. If you don’t play poker, you canread about it at wikipedia.org/wiki/Poker, but you don't haveto; I'll tell you what you need to know for the exercises.

If you are not familiar with Anglo-American playing cards,you can read about them at wikipedia.org/wiki/Playing_cards.

Card objects[edit]

There are fifty-two cards in a deck, each of which belongs to one offour suits and one of thirteen ranks. The suits are Spades, Hearts,Diamonds, and Clubs (in descending order in bridge). The ranks areAce, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, and King. Depending onthe game that you are playing, an Ace may be higher than Kingor lower than 2.

If we want to define a new object to represent a playing card, it isobvious what the attributes should be: rank andsuit. It is not as obvious what type the attributesshould be. One possibility is to use strings containing words like'Spade' for suits and 'Queen' for ranks. One problem withthis implementation is that it would not be easy to compare cards tosee which had a higher rank or suit.

An alternative is to use integers to encode the ranks and suits.In this context, “encode” means that we are going to define a mappingbetween numbers and suits, or between numbers and ranks. Thiskind of encoding is not meant to be a secret (thatwould be “encryption”).

For example, this table shows the suits and the corresponding integercodes:

Spades3
Hearts2
Diamonds1
Clubs0

This code makes it easy to compare cards; because higher suits map tohigher numbers, we can compare suits by comparing their codes.

The mapping for ranks is fairly obvious; each of the numerical ranksmaps to the corresponding integer, and for face cards:

Jack11
Queen12
King13

I am using the ↦ symbol to make it clear that these mappingsare not part of the Python program. They are part of the programdesign, but they don’t appear explicitly in the code.

The class definition for Card looks like this:

As usual, the init method takes an optionalparameter for each attribute. The default card isthe 2 of Clubs.

To create a Card, you call Card with thesuit and rank of the card you want.

Class attributes[edit]

In order to print Card objects in a way that people can easilyread, we need a mapping from the integer codes to the correspondingranks and suits. A natural way todo that is with lists of strings. We assign these lists to classattributes:

Variables like suit_names and rank_names, which aredefined inside a class but outside of any method, are calledclass attributes because they are associated with the class object Card.

This term distinguished them from variables like suit and rank, which are called instance attributes because they areassociated with a particular instance.

Both kinds of attribute are accessed using dot notation. Forexample, in __str__, self is a Card object,and self.rank is its rank. Similarly, Cardis a class object, and Card.rank_names is alist of strings associated with the class.

Every card has its own suit and rank, but thereis only one copy of suit_names and rank_names.

Putting it all together, the expressionCard.rank_names[self.rank] means “use the attribute rankfrom the object self as an index into the list rank_namesfrom the class Card, and select the appropriate string.”

The first element of rank_names is None because thereis no card with rank zero. By including None as a place-keeper,we get a mapping with the nice property that the index 2 maps to thestring '2', and so on. To avoid this tweak, we could haveused a dictionary instead of a list.

With the methods we have so far, we can create and print cards:

Here is a diagram that shows the Card class objectand one Card instance:

<IMG SRC='book026.png'>

Card is a class object, so it has type type. card1 has type Card. (To save space, I didn’t draw thecontents of suit_names and rank_names).

Comparing cards[edit]

For built-in types, there are conditional operators(<, >, , etc.)that comparevalues and determine when one is greater than, less than, or equal toanother. For user-defined types, we can override the behavior ofthe built-in operators by providing a method named__cmp__.

__cmp__ takes two parameters, self and other,and returns a positive number if the first object is greater, anegative number if the second object is greater, and 0 if they areequal to each other.

The correct ordering for cards is not obvious.For example, whichis better, the 3 of Clubs or the 2 of Diamonds? One has a higherrank, but the other has a higher suit. In order to comparecards, you have to decide whether rank or suit is more important.

The answer might depend on what game you are playing, but to keepthings simple, we’ll make the arbitrary choice that suit is moreimportant, so all of the Spades outrank all of the Diamonds,and so on.

With that decided, we can write __cmp__:

You can write this more concisely using tuple comparison:

The built-in function cmp has the same interface asthe method __cmp__: it takes two values and returnsa positive number if the first is larger, a negative numberof the second is larger, and 0 if they are equal.

Exercise 1[edit]

Write a __cmp__ method for Time objects. Hint: youcan use tuple comparison, but you also might consider usinginteger subtraction.

Decks[edit]

Now that we have Cards, the next step is to define Decks. Since adeck is made up of cards, it is natural for each Deck to contain alist of cards as an attribute.

The following is a class definition for Deck. Theinit method creates the attribute cards and generatesthe standard set of fifty-two cards:

The easiest way to populate the deck is with a nested loop. The outerloop enumerates the suits from 0 to 3. The inner loop enumerates theranks from 1 to 13. Each iterationcreates a new Card with the current suit and rank,and appends it to self.cards.

Printing the deck[edit]

Here is a __str__ method for Deck:

This method demonstrates an efficient way to accumulate a largestring: building a list of strings and then using join.The built-in function str invokes the __str__method on each card and returns the string representation.

Since we invoke join on a newline character, the cardsare separated by newlines. Here’s what the result looks like:

Even though the result appears on 52 lines, it isone long string that contains newlines.

Add, remove, shuffle and sort[edit]

To deal cards, we would like a method thatremoves a card from the deck and returns it.The list method pop provides a convenient way to do that:

Since pop removes the last card in the list, we aredealing from the bottom of the deck. In real life bottom dealing isfrowned upon1,but in this context it’s ok.

To add a card, we can use the list method append:

A method like this that uses another function without doingmuch real work is sometimes called a veneer. The metaphorcomes from woodworking, where it is common to glue a thinlayer of good quality wood to the surface of a cheaper piece ofwood.

In this case we are defining a “thin” method that expressesa list operation in terms that are appropriate for decks.

As another example, we can write a Deck method named shuffleusing the function shuffle from the random module:

Don’t forget to import random.

Exercise 2[edit]

Write a Deck method named 'sort' that uses the list method'sort' to sort the cards in a 'Deck'. 'sort' usesthe __cmp__ method we defined to determine sort order.

Inheritance[edit]

The language feature most often associated with object-orientedprogramming is inheritance. Inheritance is the ability todefine a new class that is a modified version of an existingclass.

It is called “inheritance” because the new class inherits themethods of the existing class. Extending this metaphor, the existingclass is called the parent and the new class iscalled the child.

As an example, let’s say we want a class to represent a “hand,”that is, the set of cards held by one player. A hand is similar to adeck: both are made up of a set of cards, and both require operationslike adding and removing cards.

A hand is also different from a deck; there are operations we want forhands that don’t make sense for a deck. For example, in poker wemight compare two hands to see which one wins. In bridge, we mightcompute a score for a hand in order to make a bid.

This relationship between classes—similar, but different—lendsitself to inheritance.

The definition of a child class is like other class definitions,but the name of the parent class appears in parentheses:

This definition indicates that Hand inherits from Deck;that means we can use methods like pop_card and add_cardfor Hands as well as Decks.

Hand also inherits __init__ from Deck, butit doesn’t really do what we want: instead of populating the handwith 52 new cards, the init method for Hands should initializecards with an empty list.

If we provide an init method in the Hand class, it overrides theone in the Deck class:

So when you create a Hand, Python invokes this init method:

But the other methods are inherited from Deck, so we can usepop_card and add_card to deal a card:

A natural next step is to encapsulate this code in a methodcalled move_cards:

move_cards takes two arguments, a Hand object and the number ofcards to deal. It modifies both self and hand, andreturns None.

In some games, cards are moved from one hand to another,or from a hand back to the deck. You can use move_cardsfor any of these operations: self can be either a Deckor a Hand, and hand, despite the name, can also be a Deck.

Exercise 3

Write a Deck method called deal_hands that takes twoparameters, the number of hands and the number of cards perhand, and that creates new Hand objects, deals the appropriatenumber of cards per hand, and returns a list of Hand objects.

Inheritance is a useful feature. Some programs that would berepetitive without inheritance can be written more elegantlywith it. Inheritance can facilitate code reuse, since you cancustomize the behavior of parent classes without having to modifythem. In some cases, the inheritance structure reflects the naturalstructure of the problem, which makes the program easier tounderstand.

On the other hand, inheritance can make programs difficult to read.When a method is invoked, it is sometimes not clear where to find itsdefinition. The relevant code may be scattered among several modules.Also, many of the things that can be done using inheritance can bedone as well or better without it.

Class diagrams[edit]

So far we have seen stack diagrams, which show the state ofa program, and object diagrams, which show the attributesof an object and their values. These diagrams represent a snapshotin the execution of a program, so they change as the programruns.

They are also highly detailed; for some purposes, toodetailed. A class diagrams is a more abstract representationof the structure of a program. Instead of showing individualobjects, it shows classes and the relationships between them.

There are several kinds of relationship between classes:

  • Objects in one class might contain references to objects in another class. For example, each Rectangle contains a reference to a Point, and each Deck contains references to many Cards. This kind of relationship is called HAS-A, as in, “a Rectangle has a Point.”
  • One class might inherit from another. This relationship is called IS-A, as in, “a Hand is a kind of a Deck.”
  • One class might depend on another in the sense that changes in one class would require changes in the other.

A class diagram is a graphical representation of theserelationships2. For example, this diagram shows therelationships between Card, Deck and Hand.

The arrow with a hollow triangle head represents an IS-Arelationship; in this case it indicates that Hand inheritsfrom Deck.

The standard arrow head represents a HAS-Arelationship; in this case a Deck has references to Cardobjects.

The star (*) near the arrow head is a multiplicity; it indicates how many Cards a Deck has.A multiplicity can be a simple number, like 52, a range,like 5..7 or a star, which indicates that a Deck canhave any number of Cards.

A more detailed diagram might show that a Deck actuallycontains a list of Cards, but built-in typeslike list and dict are usually not included in class diagrams.

Exercise 4[edit]

Read 'TurtleWorld.py', 'World.py' and 'Gui.py'and draw a class diagram that shows the relationships amongthe classes defined there.

Debugging[edit]

Inheritance can make debugging a challenge because when youinvoke a method on an object, you might not know which methodwill be invoked.

Suppose you are writing a function that works with Hand objects.You would like it to work with all kinds of Hands, likePokerHands, BridgeHands, etc. If you invoke a method likeshuffle, you might get the one defined in Deck,but if any of the subclasses override this method, you’llget that version instead.

Any time you are unsure about the flow of execution through yourprogram, the simplest solution is to add print statements at thebeginning of the relevant methods. If Deck.shuffle prints amessage that says something like Running Deck.shuffle, then asthe program runs it traces the flow of execution.

As an alternative, you could use this function, which takes anobject and a method name (as a string) and returns the class thatprovides the definition of the method:

Here’s an example:

So the shuffle method for this Hand is the one in Deck.

find_defining_class uses the mro method to get the listof class objects (types) that will be searched for methods. “MRO”stands for “method resolution order.”

Here’s a program design suggestion: whenever you override a method,the interface of the new method should be the same as the old. Itshould take the same parameters, return the same type, and obey thesame preconditions and postconditions. If you obey this rule, youwill find that any function designed to work with an instance of asuperclass, like a Deck, will also work with instances of subclasseslike a Hand or PokerHand.

If you violate this rule, your code will collapse like (sorry)a house of cards.

Glossary[edit]

encode:
To represent one set of values using anotherset of values by constructing a mapping between them.
class attribute:
An attribute associated with a classobject. Class attributes are defined insidea class definition but outside any method.
instance attribute:
An attribute associated with aninstance of a class.
veneer:
A method or function that provides a differentinterface to another function without doing much computation.
inheritance:
The ability to define a new class that is amodified version of a previously defined class.
parent class:
The class from which a child class inherits.
child class:
A new class created by inheriting from anexisting class; also called a “subclass.”
IS-A relationship:
The relationship between a child classand its parent class.
HAS-A relationship:
The relationship between two classeswhere instances of one class contain references to instances ofthe other.
class diagram:
A diagram that shows the classes in a programand the relationships between them.
multiplicity:
A notation in a class diagram that shows, fora HAS-A relationship, how many references there are to instancesof another class.

Exercises[edit]

Exercise 5[edit]

The following are the possible hands in poker, in increasing orderof value (and decreasing order of probability):

pair:
two cards with the same rank
'two pair:'
two pairs of cards with the same rank
'three of a kind:'
three cards with the same rank
'straight:'
five cards with ranks in sequence (aces canbe high or low, so 'Ace-2-3-4-5' is a straight and so is '10-Jack-Queen-King-Ace', but 'Queen-King-Ace-2-3' is not.)
'flush:'
five cards with the same suit
'full house:'
three cards with one rank, two cards with another
'four of a kind:'
four cards with the same rank
'straight flush:'
five cards in sequence (as defined above) andwith the same suit

The goal of these exercises is to estimatethe probability of drawing these various hands.

  • Download the following files from 'thinkpython.com/code':
    Card.py
    : A complete version of the 'Card', 'Deck' and 'Hand' classes in this chapter.
    'PokerHand.py'
    : An incomplete implementation of a class
that represents a poker hand, and some code that tests it.
  • 'If you run ''PokerHand.py'', it deals six 7-card poker hands

and checks to see if any of them contains a flush. Read thiscode carefully before you go on.'

  • 'Add methods to ''PokerHand.py'' named ''has_pair'',

''has_twopair'', etc. that return True or False according towhether or not the hand meets the relevant criteria. Your code shouldwork correctly for “hands” that contain any number of cards(although 5 and 7 are the most common sizes).'

  • 'Write a method named ''classify'' that figures out

the highest-value classification for a hand and sets the''label'' attribute accordingly. For example, a 7-card handmight contain a flush and a pair; it should be labeled “flush”.'

  • 'When you are convinced that your classification methods are

working, the next step is to estimate the probabilities of the varioushands. Write a function in ''PokerHand.py'' that shuffles a deck ofcards, divides it into hands, classifies the hands, and counts thenumber of times various classifications appear.'

  • 'Print a table of the classifications and their probabilities.

Run your program with larger and larger numbers of hands until theoutput values converge to a reasonable degree of accuracy. Compareyour results to the values at ''wikipedia.org/wiki/Hand_rankings''.'

Exercise 6[edit]

This exercise uses TurtleWorld from Chapter '4'.You will write code that makes Turtles play tag. If youare not familiar with the rules of tag, see'wikipedia.org/wiki/Tag_(game)'.

  • Download 'thinkpython.com/code/Wobbler.py' and run it. You

should see a TurtleWorld with three Turtles. If you press the'Run' button, the Turtles wander at random.

  • Read the code and make sure you understand how it works.

The 'Wobbler' class inherits from 'Turtle', which meansthat the 'Turtle' methods 'lt', 'rt', 'fd'and 'bk' work on Wobblers.The 'step' method gets invoked by TurtleWorld. It invokes 'steer', which turns the Turtle in the desired direction,'wobble', which makes a random turn in proportion to the Turtle’sclumsiness, and 'move', which moves forward a few pixels,depending on the Turtle’s speed.

  • Create a file named 'Tagger.py'. Import everything from

'Wobbler', then define a class named 'Tagger' that inheritsfrom 'Wobbler'. Call make_world passing the 'Tagger' class object as an argument.

  • Add a 'steer' method to 'Tagger' to override the one in

'Wobbler'. As a starting place, write a version that alwayspoints the Turtle toward the origin. Hint: use the math function'atan2' and the Turtle attributes 'x', 'y' and'heading'.

  • Modify 'steer' so that the Turtles stay in bounds.

For debugging, you might want to use the 'Step' button,which invokes 'step' once on each Turtle.

  • Modify 'steer' so that each Turtle points toward its nearest

neighbor. Hint: Turtles have an attribute, 'world', that is areference to the TurtleWorld they live in, and the TurtleWorld hasan attribute, 'animals', that is a list of all Turtles in theworld.

  • Modify 'steer' so the Turtles play tag. You can add methods

to 'Tagger' and you can override 'steer' and__init__, but you may not modify or override 'step', 'wobble' or 'move'. Also, 'steer' is allowed to change theheading of the Turtle but not the position.Adjust the rules and your 'steer' method for good quality play;for example, it should be possible for the slow Turtle to tag thefaster Turtles eventually.

You can get my solution from 'thinkpython.com/code/Tagger.py'.

1
See wikipedia.org/wiki/Bottom_dealing.
2
The diagrams I am using here are similar to UML(see wikipedia.org/wiki/Unified_Modeling_Language), with a fewsimplifications.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.
A Wikibookian has nominated this page for cleanup because:
You can help make it better. Please review any relevant discussion.

Different kinds of errors can occurin a program, and it is useful to distinguish among themin order to track them down more quickly:

  • Syntax errors are produced by Python when it is translating the source code into byte code. They usually indicate that there is something wrong with the syntax of the program. Example: Omitting the colon at the end of a def statement yields the somewhat redundant message SyntaxError: invalid syntax.
  • Runtime errors are produced by the interpreter if something goes wrong while the program is running. Most runtime error messages include information about where the error occurred and what functions were executing. Example: An infinite recursion eventually causes the runtime error “maximum recursion depth exceeded.”
  • Semantic errors are problems with a program that runs without producing error messages but doesn’t do the right thing. Example: An expression may not be evaluated in the order you expect, yielding an incorrect result.

The first step in debugging is to figure out which kind oferror you are dealing with. Although the following sections areorganized by error type, some techniques areapplicable in more than one situation.

Syntax errors[edit]

Syntax errors are usually easy to fix once you figure out what theyare. Unfortunately, the error messages are often not helpful.The most common messages are SyntaxError: invalid syntax andSyntaxError: invalid token, neither of which is very informative.

On the other hand, the message does tell you where in the program theproblem occurred. Actually, it tells you where Pythonnoticed a problem, which is not necessarily where the erroris. Sometimes the error is prior to the location of the errormessage, often on the preceding line.

If you are building the program incrementally, you should havea good idea about where the error is. It will be in the lastline you added.

If you are copying code from a book, start by comparingyour code to the book’s code very carefully. Check every character.At the same time, remember that the book might be wrong, soif you see something that looks like a syntax error, it might be.

Here are some ways to avoid the most common syntax errors:

  • Make sure you are not using a Python keyword for a variable name.
  • Check that you have a colon at the end of the header of every

compound statement, including for, while,if, and def statements.


  • Make sure that any strings in the code have matching

quotation marks.

  • If you have multiline strings with triple quotes (single or double), make

sure you have terminated the string properly. An unterminated stringmay cause an invalid token error at the end of your program,or it may treat the following part of the program as a string until itcomes to the next string. In the second case, it might not produce an errormessage at all!


  • An unclosed opening operator—(, {, or

[—makes Python continue with the next line as part of thecurrent statement. Generally, an error occurs almost immediately inthe next line.

  • Check for the classic = instead of inside

a conditional.

  • Check the indentation to make sure it lines up the way it

is supposed to. Python can handle space and tabs, but if you mixthem it can cause problems. The best way to avoid this problemis to use a text editor that knows about Python and generatesconsistent indentation.

If nothing works, move on to the next section...

I keep making changes and it makes no difference.[edit]

If the interpreter says there is an error and you don’t see it, thatmight be because you and the interpreter are not looking at the samecode. Check your programming environment to make sure that theprogram you are editing is the one Python is trying to run.

If you are not sure, try putting an obvious and deliberate syntaxerror at the beginning of the program. Now run it again. If theinterpreter doesn’t find the new error, you are not running thenew code.

There are a few likely culprits:

  • You edited the file and forgot to save the changes before running it again. Some programming environments do this for you, but some don’t.
  • You changed the name of the file, but you are still running the old name.
  • Something in your development environment is configured incorrectly.
  • If you are writing a module and using import, make sure you don’t give your module the same name as one of the standard Python modules.
  • If you are using import to read a module, remember that you have to restart the interpreter or use reload to read a modified file. If you import the module again, it doesn’t do anything.

If you get stuck and you can’t figure out what is going on, oneapproach is to start again with a new program like “Hello, World!,”and make sure you can get a known program to run. Then gradually addthe pieces of the original program to the new one.

Runtime errors[edit]

Once your program is syntactically correct,Python can compile it and at least start running it. What couldpossibly go wrong?

My program does absolutely nothing.[edit]

This problem is most common when your file consists of functions andclasses but does not actually invoke anything to start execution.This may be intentional if you only plan to import this module tosupply classes and functions.

If it is not intentional, make sure that youare invoking a function to start execution, or execute one fromthe interactive prompt. Also see the “Flow of Execution” sectionbelow.

My program hangs[edit]

If a program stops and seems to be doing nothing, it is “hanging.”Often that means that it is caught in an infinite loop or infiniterecursion.

  • If there is a particular loop that you suspect is the problem, add a print statement immediately before the loop that says “entering the loop” and another immediately after that says “exiting the loop.” Run the program. If you get the first message and not the second, you’ve got an infinite loop. Go to the “Infinite Loop” section below.
  • Most of the time, an infinite recursion will cause the program to run for a while and then produce a “RuntimeError: Maximum recursion depth exceeded” error. If that happens, go to the “Infinite Recursion” section below. If you are not getting this error but you suspect there is a problem with a recursive method or function, you can still use the techniques in the “Infinite Recursion” section.
  • If neither of those steps works, start testing other loops and other recursive functions and methods.
  • If that doesn’t work, then it is possible that you don’t understand the flow of execution in your program. Go to the “Flow of Execution” section below.

Infinite Loop[edit]

If you think you have an infinite loop and you think you knowwhat loop is causing the problem, add a print statement atthe end of the loop that prints the values of the variables inthe condition and the value of the condition.

For example:

Now when you run the program, you will see three lines of outputfor each time through the loop. The last time through theloop, the condition should be false. If the loop keepsgoing, you will be able to see the values of x and y,and you might figure out why they are not being updated correctly.

Infinite Recursion[edit]

Most of the time, an infinite recursion will cause the program to runfor a while and then produce a Maximum recursion depth exceedederror.

If you suspect that a function or method is causing an infiniterecursion, start by checking to make sure that there is a base case.In other words, there should be some condition that will cause thefunction or method to return without making a recursive invocation.If not, then you need to rethink the algorithm and identify a basecase.

If there is a base case but the program doesn’t seem to be reachingit, add a print statement at the beginning of the function or methodthat prints the parameters. Now when you run the program, you will seea few lines of output every time the function or method is invoked,and you will see the parameters. If the parameters are not movingtoward the base case, you will get some ideas about why not.

Flow of Execution[edit]

If you are not sure how the flow of execution is moving throughyour program, add print statements to the beginning of eachfunction with a message like “entering function foo,” wherefoo is the name of the function.

Now when you run the program, it will print a trace of eachfunction as it is invoked.

When I run the program I get an exception.[edit]

If something goes wrong during runtime, Pythonprints a message that includes the name of theexception, the line of the program where the problem occurred,and a traceback.

The traceback identifies the function that is currently running,and then the function that invoked it, and then the function thatinvoked that, and so on. In other words, it traces thesequence of function invocations that got you to where you are. Italso includes the line number in your file where each of thesecalls occurs.

The first step is to examine the place in the program wherethe error occurred and see if you can figure out what happened.These are some of the most common runtime errors:

NameError:
You are trying to use a variable that doesn’texist in the current environment.Remember that local variables are local. Youcannot refer to them from outside the function where they are defined.
TypeError:
There are several possible causes:
  • You are trying to use a value improperly. Example: indexing a string, list, or tuple with something other than an integer.
  • There is a mismatch between the items in a format string and the items passed for conversion. This can happen if either the number of items does not match or an invalid conversion is called for.
  • You are passing the wrong number of arguments to a function or method. For methods, look at the method definition and check that the first parameter is self. Then look at the method invocation; make sure you are invoking the method on an object with the right type and providing the other arguments correctly.
KeyError:
You are trying to access an element of a dictionaryusing a key that the dictionary does not contain.
AttributeError:
You are trying to access an attribute or methodthat does not exist. Check the spelling! You can usedir to list the attributes that do exist.If an AttributeError indicates that an object has NoneType,that means that it is None. One common cause is forgettingto return a value from a function; if you get to the end ofa function without hitting a return statement, it returnsNone. Another common cause is using the result froma list method, like sort, that returns None.
IndexError:
The index you are usingto access a list, string, or tuple is greater thanits length minus one. Immediately before the site of the error,add a print statement to displaythe value of the index and the length of the array.Is the array the right size? Is the index the right value?

The Python debugger (pdb) is useful for tracking downExceptions because it allows you to examine the state of theprogram immediately before the error. You can readabout pdb at docs.python.org/lib/module-pdb.html.

I added so many print statements I get inundated with output[edit]

One of the problems with using print statements for debuggingis that you can end up buried in output. There are two waysto proceed: simplify the output or simplify the program.

To simplify the output, you can remove or comment out printstatements that aren’t helping, or combine them, or formatthe output so it is easier to understand.

To simplify the program, there are several things you can do. First,scale down the problem the program is working on. For example, if youare searching a list, search a small list. If the program takesinput from the user, give it the simplest input that causes theproblem.

Second, clean up the program. Remove dead code and reorganize theprogram to make it as easy to read as possible. For example, if yoususpect that the problem is in a deeply nested part of the program,try rewriting that part with simpler structure. If you suspect alarge function, try splitting it into smaller functions and testing themseparately.

Often the process of finding the minimal test case leads you to thebug. If you find that a program works in one situation but not inanother, that gives you a clue about what is going on.

Similarly, rewriting a piece of code can help you find subtlebugs. If you make a change that you think doesn’t affect theprogram, and it does, that can tip you off.

Semantic errors[edit]

In some ways, semantic errors are the hardest to debug,because the interpreter provides no informationabout what is wrong. Only you know what the program is supposed todo.

The first step is to make a connection between the programtext and the behavior you are seeing. You need a hypothesisabout what the program is actually doing. One of the thingsthat makes that hard is that computers run so fast.

You will often wish that you could slow the program down to humanspeed, and with some debuggers you can. But the time it takes toinsert a few well-placed print statements is often short compared tosetting up the debugger, inserting and removing breakpoints, and“stepping” the program to where the error is occurring.

My program doesn’t work.[edit]

You should ask yourself these questions:

  • Is there something the program was supposed to do but which doesn’t seem to be happening? Find the section of the code that performs that function and make sure it is executing when you think it should.
  • Is something happening that shouldn’t? Find code in your program that performs that function and see if it is executing when it shouldn’t.
  • Is a section of code producing an effect that is not what you expected? Make sure that you understand the code in question, especially if it involves invocations to functions or methods in other Python modules. Read the documentation for the functions you invoke. Try them out by writing simple test cases and checking the results.

In order to program, you need to have a mental model of howprograms work. If you write a program that doesn’t do what you expect,very often the problem is not in the program; it’s in your mentalmodel.

The best way to correct your mental model is to break the programinto its components (usually the functions and methods) and testeach component independently. Once you find the discrepancybetween your model and reality, you can solve the problem.

Of course, you should be building and testing components as youdevelop the program. If you encounter a problem,there should be only a small amount of new codethat is not known to be correct.

I’ve got a big hairy expression and it doesn’t do what I expect.[edit]

Writing complex expressions is fine as long as they are readable,but they can be hard to debug. It is often a good idea tobreak a complex expression into a series of assignments totemporary variables.

For example:

This can be rewritten as:

The explicit version is easier to read because the variablenames provide additional documentation, and it is easier to debugbecause you can check the types of the intermediate variablesand display their values.

Another problem that can occur with big expressions isthat the order of evaluation may not be what you expect.For example, if you are translating the expressionx/2 π into Python, you might write:

That is not correct because multiplication and division havethe same precedence and are evaluated from left to right.So this expression computes x π / 2.

A good way to debug expressions is to add parentheses to makethe order of evaluation explicit:

Whenever you are not sure of the order of evaluation, useparentheses. Not only will the program be correct (in the senseof doing what you intended), it will also be more readable forother people who haven’t memorized the rules of precedence.

I’ve got a function or method that doesn’t return what I expect[edit]

If you have a return statement with a complex expression,you don’t have a chance to print the return value beforereturning. Again, you can use a temporary variable. Forexample, instead of:

you could write:

Now you have the opportunity to display the value ofcount before returning.

I'm really, really stuck and I need help.[edit]

First, try getting away from the computer for a few minutes.Computers emit waves that affect the brain, causing thesesymptoms:

  • Frustration and rage.
  • Superstitious beliefs (“the computer hates me”) and

magical thinking (“the program only works when I wear myhat backward”).

  • Random walk programming (the attempt to program by writing

every possible program and choosing the one that does the rightthing).

If you find yourself suffering from any of these symptoms, getup and go for a walk. When you are calm, think about the program.What is it doing? What are some possible causes of thatbehavior? When was the last time you had a working program,and what did you do next?

Sometimes it just takes time to find a bug. I often find bugswhen I am away from the computer and let my mind wander. Someof the best places to find bugs are trains, showers, and in bed,just before you fall asleep.

No, I really need help.[edit]

It happens. Even the best programmers occasionally get stuck.Sometimes you work on a program so long that you can’t see theerror. A fresh pair of eyes is just the thing.

Before you bring someone else in, make sure you are prepared.Your program should be as simpleas possible, and you should be working on the smallest inputthat causes the error. You should have print statements in theappropriate places (and the output they produce should becomprehensible). You should understand the problem well enoughto describe it concisely.

When you bring someone in to help, be sure to givethem the information they need:

  • If there is an error message, what is it and what part of the program does it indicate?
  • What was the last thing you did before this error occurred? What were the last lines of code that you wrote, or what is the new test case that fails?
  • What have you tried so far, and what have you learned?

When you find the bug, take a second to think about what youcould have done to find it faster. Next time you see somethingsimilar, you will be able to find the bug more quickly.

Remember, the goal is not just to make the programwork. The goal is to learn how to make the program work.

Chapter 1[edit]

See below for Chapter 1 exercises.

Exercise 1.4[edit]

If you run a 10 kilometer race in 43 minutes 30 seconds, what is your average time per mile? What is your average speed in miles per hour? (Hint: there are about 1.61 kilometers in a mile.)

Chapter 2[edit]

Exercise 2.1[edit]

If you type an integer with a leading zero, you might get a confusing error:

Other number seem to work, but the results are bizarre:

So python is assuming you want to convert an octal number to a decimal number. In the base 8 numbering system where valid numbers are 0, 1, 2, 3, 4, 5, 6 and 7.

Every 8 numbers we increment the left hand columns. This means that the right most column is the number of 'ones'. The one to the left of that is a tally of the number of 'eights', the one next to that is a tally of a full column of 'eight' times the 'eight column' - 64. The one next to that is 64*8 - 512 and so on.For more information read Base Eight math.

That is why zipcode = 02492 is invalid as the digit 9 is not a valid octal number. We can do the conversion manually as follows:

Exercise 2.2[edit]

The volume of a sphere with radius r is 4/3 π r3.What is the volume of a sphere with radius 5?

Suppose the cover price of a book is $24.95, but bookstores get a 40% discount. Shipping costs $3 for the first copy and 75 cents for each additional copy. What is the total wholesale cost for 60 copies?

Another solution using functions as well as input prompts:

If I leave my house at 6:52 am and run 1 mile at an easy pace (8:15 per mile), then 3 miles at tempo (7:12 per mile) and 1 mile at easy pace again, what time do I get home for breakfast?

Answer: 7:30 am

How I did it:

Chapter 3[edit]

Exercise 3.3[edit]

Python provides a built-in function called len that returns the length of a string, so the value of len('allen') is 5. Write a function named right_justify that takes a string named s as a parameter and prints the string with enough leading spaces so that the last letter of the string is in column 70 of the display.



Alternate Solution Using concatenation and repetition

Exercise 3.5[edit]

You can see my solution at http://thinkpython.com/code/grid.py.

Chapter 4[edit]

4.3 Exercise 1[edit]

4.3 Exercise 2[edit]

4.3 Exercise 3[edit]

Chapter 5[edit]

Exercise 5.2[edit]

Chapter 9[edit]

Exercise 9.1[edit]

Exercise 9.2[edit]

Exercise 9.3[edit]

Exercise 9.4[edit]

Chapter 10[edit]

Exercise 10.1[edit]

Write a function called nested_sum that takes a nested list of integers and add up the elements from all of the nested lists.

Exercise 10.2[edit]

Write a function named 'capitalize_nested' that takes a nested list of strings and returns a new nested list with all strings capitalized.

Exercise 10.3[edit]

Write a function that takes a list of numbers and returns the cumulative sum.

Exercise 10.4[edit]

Write a function called middle that takes a list and returns a new list that contains all but the first and last elements.

This can also be done simply with a slice.

Exercise 10.5[edit]

Write a function called chop that takes a list and modifies it, removing the first and last elements, and returns None.

Chapter 11[edit]

Exercise 11.1[edit]

Write a function that reads the words in words.txt and stores them as keys in a dictionary. It doesn’t matter what the values are. Then you can use the in operator as a fast way to check whether a string is in the dictionary.

Exercise 11.2[edit]

Exercise 11.3[edit]

Dictionaries have a method called keys that returns the keys of the dictionary, in no particular order, as a list. Modify print_hist to print the keys and their values in alphabetical order.

OR

Exercise 11.4[edit]

Modify reverse_lookup so that it builds and returns a list of all keys that map to v, or an empty list if there are none.

Chapter 12[edit]

Exercise 12.1[edit]

or

or

or

Exercise 12.2[edit]

or

Exercise 12.3[edit]

Chapter 13[edit]

Exercise 13.7[edit]

Chapter 14[edit]

Exercise 14.3[edit]

Exercise 14.5[edit]

Chapter 15[edit]

Exercise 15.1[edit]

Chapter 16[edit]

Exercise 16.1[edit]

or

Exercise 16.2[edit]

Exercise 16.3[edit]

or

Exercise 16.4[edit]

Exercise 16.5[edit]

Exercise 16.6[edit]

Exercise 16.7[edit]

Write a class definition for a Date object that has attributes day, month and year. Write a function called increment_date that takes a Date object, date, and an integer, n, and returns a new Date object that represents the day n days after date. Hint: “Thirty days hath September...” Challenge: does your function deal with leap years correctly? See wikipedia.org/wiki/Leap_year.

Exercise 16.8[edit]

1. Use the datetime module to write a program that gets the current date and prints the day of the week.

2. Write a program that takes a birthday as input and prints the user’s age and the number of days, hours, minutes and seconds until their next birthday.

Chapter 17[edit]

Exercise 17.8[edit]

2.

3. Download http://thinkpython.com/code/color_list.py and use the function read_colors to generate a list of the available colors on your system, their names and RGB values. For each named color draw a sphere in the position that corresponds to its RGB values.

Chapter 3.5[edit]

calculator[edit]

palindrome[edit]

sum of all digits[edit]

Exercise 18.5[edit]

Appendix B[edit]

Exercise B.3[edit]

Write a function called bisection that takes a sorted list and a target value and returns the index of the value in the list, if it’s there, or None if it’s not.

Index[edit]

Ackerman function, 6.11


  • AttributeError, 15.7, A.2.3


  • Austin, Jane, 13.3


  • abecedarian, 8.3, 9.2


  • abs function, 6.1


  • absolute path, 14.4, 14.11


  • access, 10.2


  • accumulator, 10.14


histogram, 13.3


  • list, 10.7


  • string, 18.5


  • sum, 10.7



  • add method, 17.7


  • addition with carrying, 7.6


  • algorithm, 1.2, 1.7, 7.6, 13.7


Euclid, 6.11


  • MD5, 14.12


  • RSA, 11.7


  • square root, 7.9



  • aliasing, 10.10, 10.11, 10.14, 15.2, 15.6, 17.12


copying to avoid, 10.13



  • alphabet, 4.12


  • alternative execution, 5.5


  • ambiguity, 1.4


  • anagram, 10.15


  • anagram set, 12.11, 14.7


  • and operator, 5.3


  • anydbm module, 14.6


  • append method, 10.6, 10.12, 10.15, 18.4, 18.6


  • arc function, 4.3


  • argument, 3.1, 3.5, 3.8, 3.8, 3.14, 10.12


gather, 12.4


  • keyword, 4.5, 4.11, 12.7, 19.2


  • list, 10.12


  • optional, 8.8, 10.9, 11.3


  • variable-length tuple, 12.4



  • argument scatter, 12.4


  • arithmetic operator, 2.5


  • assert statement, 16.5


  • assignment, 2.11, 7.1, 10.1


item, 8.5, 10.2, 12.1


  • multiple, 7.8, 11.6


  • tuple, 12.2, 12.3, 12.5, 12.10



  • assignment statement, 2.2


  • attribute

__dict__, 17.10


  • class, 18.2, 18.10


  • initializing, 17.10


  • instance, 15.2, 15.8, 18.2, 18.10



  • available colors, 15.9, 17.12



  • Bacon, Kevin, 14.12


  • Bangladesh, national flag, 15.9


  • Button widget, 19.2


  • base case, 5.9, 5.13


  • benchmarking, 13.9, 13.11


  • big, hairy expression, A.3.2


  • binding, 19.8, 19.10


  • bingo, 12.11


  • birthday, 16.7


  • birthday paradox, 10.15


  • bisect module, 10.15


  • bisection search, 10.15


  • bisection, debugging by, 7.7


  • bitwise operator, 2.5


  • body, 3.5, 3.14, 5.13, 7.3


  • bool type, 5.2


  • boolean expression, 5.2, 5.13


  • boolean function, 6.4, 16.1


  • boolean operator, 8.9


  • borrowing, subtraction with, 7.6, 16.4


  • bound method, 19.6, 19.10


  • bounding box, 15.9, 19.4, 19.10


  • bracket

squiggly, 11



  • bracket operator, 8.1, 10.2, 12.1


  • branch, 5.5, 5.13


  • break statement, 7.4


  • bug, 1.3, 1.3, 1.7


worst, 17.12


  • worst ever, 19.11




  • Callable object, 19.7


  • Canvas coordinate, 19.3, 19.8


  • Canvas item, 19.3


  • Canvas object, 15.9


  • Canvas widget, 19.3


  • Car Talk, 9.7, 9.7, 9.7, 11.10, 12.11


  • Card class, 18.1


  • Collatz conjecture, 7.3


  • Czech Republic, national flag, 15.9


  • calculator, 1.8, 2.12


  • call graph, 11.5, 11.9


  • callback, 19.2, 19.6, 19.7, 19.8, 19.9, 19.10


  • card, playing, 18


  • carrying, addition with, 7.6, 16.2, 16.4


  • case-sensitivity, variable names, 2.10


  • catch, 14.11


  • chained conditional, 5.6, 5.13


  • character, 8.1


  • checksum, 14.12


  • child class, 18.7, 18.10


  • choice function, 13.2


  • circle function, 4.3


  • circular definition, 6.5


  • class, 15.1, 15.8


Card, 18.1


  • Date, 16.7


  • Deck, 18.4


  • Hand, 18.7


  • Kangaroo, 17.12


  • Point, 15.1, 17.5


  • parent, 18.7


  • Rectangle, 15.3


  • SimpleTurtleWorld, 19.6


  • Time, 16.1



  • class attribute, 18.2, 18.10


  • class definition, 15.1


  • class diagram, 18.8, 18.10


  • class object, 15.1, 15.8


  • close method, 14.2, 14.6, 14.8


  • cmp function, 18.3


  • __cmp__ method, 18.3


  • colon, 3.5, A.1


  • color list, 15.9, 17.12


  • comment, 2.9, 2.11


  • commutativity, 2.8, 17.8


  • compare function, 6.1


  • comparison

string, 8.10


  • tuple, 12.7, 18.3



  • comparison operator, 5.2


  • compile, 1.1, 1.7


  • composition, 3.4, 3.8, 3.14, 6.3, 18.4


  • compound statement, 5.4, 5.13


  • compression

file, 14.8



  • concatenation, 2.8, 2.11, 3.9, 8.3, 8.5, 10.9


list, 10.4, 10.12, 10.15



  • condition, 5.4, 5.13, 7.3, A.2.2


  • conditional, A.1


chained, 5.6, 5.13


  • nested, 5.7, 5.13



  • conditional execution, 5.4


  • conditional operator, 18.3


  • conditional statement, 5.4, 5.13, 6.4


  • config method, 19.3


  • consistency check, 11.8, 16.4


  • contributors, 0


  • conversion

type, 3.2



  • coordinate

Canvas, 19.3, 19.8


  • pixel, 19.8



  • coordinate sequence, 19.4


  • copy

deep, 15.6


  • shallow, 15.6


  • slice, 8.4, 10.5


  • to avoid aliasing, 10.13



  • copy module, 15.6


  • copying objects, 15.6


  • count method, 8.8


  • counter, 8.7, 8.12, 11.1, 11.6


  • counting and looping, 8.7


  • crosswords, 9.1


  • cummings, e. e., 1.3.1


  • cumulative sum, 10.7



  • Date class, 16.7


  • Deck class, 18.4


  • Dijkstra, Edsger, 9.5


  • Doyle, Arthur Conan, 1.3.4


  • DSU pattern, 12.7, 12.10, 13.4


  • data structure, 12.9, 12.10, 13.9


  • database, 14.6, 14.11, 14.12


  • datetime module, 16.7


  • dead code, 6.1, 6.10, A.2.4


  • debugger (pdb), A.2.3


  • debugging, 1.3, 1.3, 1.6, 1.7, 2.10, 3.13, 4.10, 5.12, 6.9, 8.11, 9.5, 10.13, 11.8, 12.9, 13.10, 14.10, 15.7, 16.5, 17.10, 18.9, 19.9, A


by bisection, 7.7


  • emotional response, 1.6, A.3.4


  • experimental, 1.3.4


  • superstition, A.3.4



  • deck, playing cards, 18.4


  • declaration, 11.6, 11.9


  • decorate-sort-undecorate pattern, 12.7


  • decrement, 7.2, 7.8


  • deep copy, 15.6, 15.8


  • deepcopy function, 15.6


  • def keyword, 3.5


  • default value, 13.5, 13.11, 17.5


avoiding mutable, 17.12



  • definition

circular, 6.5


  • class, 15.1


  • function, 3.5


  • recursive, 12.11



  • del operator, 10.8


  • deletion, element of list, 10.8


  • delimiter, 10.9, 10.14


  • deterministic, 13.2, 13.11


  • development plan, 4.11


encapsulation and generalization, 4.8


  • incremental, 6.2, A.1


  • planned, 16.4


  • problem recognition, 9.3, 9.4


  • prototype and patch, 16.2, 16.4


  • random walk programming, 13.10, A.3.4



  • diagram

call graph, 11.9


  • class, 18.8, 18.10


  • object, 15.2, 15.3, 15.6, 15.8, 16.1, 18.2


  • stack, 3.10, 10.12


  • state, 2.2, 7.1, 8.11, 10.2, 10.10, 10.11, 11.4, 12.6, 15.2, 15.3, 15.6, 16.1, 18.2



  • __dict__ attribute, 17.10


  • dict function, 11


  • dictionary, 11, 11, 11.9, 12.6, A.2.3


initialize, 12.6


  • invert, 11.4


  • lookup, 11.3


  • looping with, 11.2


  • reverse lookup, 11.3


  • subtraction, 13.6


  • traversal, 12.6, 17.10



  • dictionary methods

anydbm module, 14.6



  • directory, 14.4, 14.11


walk, 14.4


  • working, 14.4



  • dispatch

type-based, 17.9



  • dispatch, type-based, 17.8


  • divisibility, 5.1


  • division

floating-point, 2.5


  • floor, 2.5, 5.12



  • divmod, 12.3, 16.4


  • docstring, 4.9, 4.11, 15.1


  • documentation, 1.8


  • dot notation, 3.3, 3.14, 8.8, 15.2, 17.2, 18.2


  • double letters, 9.7


  • drag-and-drop, 19.8


  • duplicate, 10.15, 10.15, 11.10, 14.12



  • Einstein, Albert, 4.6


  • Entry widget, 19.5


  • Euclid’s algorithm, 6.11


  • Event object, 19.8


  • element, 10.1, 10.14


  • element deletion, 10.8


  • elif keyword, 5.6


  • ellipses, 3.5


  • else keyword, 5.5


  • email address, 12.2


  • embedded object, 15.3, 15.8, 17.12


copying, 15.6



  • emotional debugging, 1.6, A.3.4


  • empty list, 10.1


  • empty string, 8.12, 10.9


  • encapsulation, 4.4, 4.11, 6.3, 7.5, 8.7, 18.7


  • encode, 18.1, 18.10


  • encrypt, 18.1


  • encryption, 11.7


  • end of line character, 14.10


  • enumerate function, 12.5


  • epsilon, 7.5


  • equality and assignment, 7.1


  • equivalence, 10.10


  • equivalent, 10.14


  • error

compile-time, A


  • runtime, 1.3.2, 2.10, 5.10, 5.12, A


  • semantic, 1.3.3, 2.1, 2.10, 8.11, A, A.3


  • shape, 12.9


  • syntax, 1.3.1, 2.10, A



  • error checking, 6.8


  • error message, 1.3.1, 1.3.3, 1.6, 2.1, 2.10, A.1


  • eval function, 7.9


  • evaluate, 2.6


  • event, 19.10


  • event handler, 19.8


  • event loop, 19.1, 19.10


  • event string, 19.8


  • event-driven programming, 19.2, 19.9, 19.10


  • exception, 1.3.2, 1.7, 2.10, A, A.2.3


AttributeError, 15.7, A.2.3


  • IndexError, 8.2, 8.11, 10.2, A.2.3


  • IOError, 14.5


  • KeyError, 11, A.2.3


  • NameError, 3.9, A.2.3


  • OverflowError, 5.12


  • RuntimeError, 5.10


  • SyntaxError, 3.4


  • TypeError, 8.1, 8.5, 11.4, 12.1, 12.4, 14.3, 17.3, A.2.3


  • UnboundLocalError, 11.6


  • ValueError, 5.11, 11.3, 12.2



  • exception, catching, 14.5


  • executable, 1.1, 1.7


  • exercise, secret, 14.12


  • exists function, 14.4


  • experimental debugging, 1.3.4, 13.10


  • expression, 2.5, 2.6, 2.11


big and hairy, A.3.2


  • boolean, 5.2, 5.13



  • extend method, 10.6



  • False special value, 5.2


  • Fermat’s Last Theorem, 5.14


  • Frame widget, 19.6


  • Free Documentation License, GNU, 0, 0


  • factorial function, 6.5, 6.8


  • fibonacci function, 6.7, 11.5


  • file, 14


compression, 14.8


  • permission, 14.5


  • reading and writing, 14.2



  • file object, 9.1, 9.6


  • filename, 14.4


  • filter pattern, 10.7, 10.14


  • find function, 8.6


  • flag, 11.6, 11.9


  • float function, 3.2


  • float type, 2.1


  • floating-point, 2.11, 7.5


  • floating-point division, 2.5


  • floor division, 2.5, 2.11, 5.12


  • flow of execution, 3.7, 3.14, 6.7, 6.9, 7.3, 18.9, 19.9, A.2.2


  • flower, 4.12


  • folder, 14.4


  • for loop, 4.2, 8.3, 10.3, 12.5


  • formal language, 1.4, 1.7


  • format operator, 14.3, 14.11, A.2.3


  • format sequence, 14.3, 14.11


  • format string, 14.3, 14.11


  • frabjuous, 6.5


  • frame, 3.10, 3.14, 5.9, 6.5, 11.5


  • frequency, 11.1


letter, 12.11


  • word, 13.1, 13.12



  • fruitful function, 3.11, 3.14


  • frustration, A.3.4


  • function, 3.5, 3.14, 17.1


abs, 6.1


  • ack, 6.11


  • arc, 4.3


  • choice, 13.2


  • circle, 4.3


  • cmp, 18.3


  • compare, 6.1


  • deepcopy, 15.6


  • dict, 11


  • enumerate, 12.5


  • eval, 7.9


  • exists, 14.4


  • factorial, 6.5


  • fibonacci, 6.7, 11.5


  • find, 8.6


  • float, 3.2


  • getattr, 17.10


  • getcwd, 14.4


  • hasattr, 15.7, 17.10


  • int, 3.2


  • isinstance, 6.8, 17.8


  • len, 3.15, 8.2, 11


  • list, 10.9


  • log, 3.3


  • max, 12.3, 12.4


  • min, 12.3, 12.4


  • open, 9.1, 9.1, 14.2, 14.5, 14.6


  • polygon, 4.3


  • popen, 14.8


  • randint, 10.15, 13.2


  • random, 12.7, 13.2


  • raw_input, 5.11


  • recursive, 5.8


  • reload, 14.9, A.1.1


  • repr, 14.10


  • reversed, 12.8


  • shuffle, 18.6


  • sorted, 12.8


  • sqrt, 3.3, 6.2


  • str, 3.2


  • sum, 12.4


  • tuple, 12.1


  • type, 15.7


  • zip, 12.5



  • function argument, 3.8


  • function call, 3.1, 3.14


  • function composition, 6.3


  • function definition, 3.5, 3.6, 3.14, 3.14


  • function frame, 3.10, 3.14, 5.9, 11.5


  • function object, 3.5, 3.15


  • function parameter, 3.8


  • function syntax, 17.2


  • function type

modifier, 16.3


  • pure, 16.2



  • function, fruitful, 3.11


  • function, math, 3.3


  • function, reasons for, 3.12


  • function, trigonometric, 3.3


  • function, tuple as return value, 12.3


  • function, void, 3.11


  • functional programming style, 16.3, 16.6



  • GCD (greatest common divisor), 6.11


  • GNU Free Documentation License, 0, 0


  • GUI, 19.1, 19.10


  • Gui module, 19.1


  • gamma function, 6.8


  • gather, 12.4, 12.10


  • generalization, 4.5, 4.11, 9.3, 16.4


  • geometry manager, 19.6, 19.10


  • get method, 11.1


  • getattr function, 17.10


  • getcwd function, 14.4


  • global statement, 11.6


  • global variable, 11.6, 11.9


update, 11.6



  • graphical user interface, 19.1


  • greatest common divisor (GCD), 6.11


  • grid, 3.15


  • guardian pattern, 6.8, 6.10, 8.11


  • gzip (Unix command), 14.8



  • HAS-A relationship, 18.8, 18.10


  • Hand class, 18.7


  • Hello, World, 1.5


  • Holmes, Sherlock, 1.3.4


  • HTMLParser module, 19.11


  • hanging, A.2.2


  • hasattr function, 15.7, 17.10


  • hash function, 11.4, 11.9


  • hashable, 11.4, 11.9, 12.6


  • hashtable, 11, 11.9


  • header, 3.5, 3.14, A.1


  • help utility, 1.8


  • hexadecimal, 15.1


  • high-level language, 1.1, 1.7


  • histogram, 11.1, 11.1, 11.9


random choice, 13.2, 13.7


  • word frequencies, 13.3



  • homophone, 11.10


  • hyperlink, 19.11


  • hypotenuse, 6.2



  • IMDb (Internet Movie Database), 14.12


  • Image module, 19.11


  • IndexError, 8.2, 8.11, 10.2, A.2.3


  • Internet Movie Database (IMDb), 14.12


  • IOError, 14.5


  • IS-A relationship, 18.8, 18.10


  • identical, 10.14


  • identity, 10.10


  • if statement, 5.4


  • image viewer, 19.11


  • immutability, 8.5, 8.5, 8.12, 10.11, 11.4, 12.1, 12.8


  • implementation, 11.1, 11.9, 13.9


  • import statement, 3.14, 4.1, 14.9


  • in operator, 8.9, 9.3, 10.2, 11


  • increment, 7.2, 7.8, 16.3, 17.3


  • incremental development, 6.10, A.1


  • indentation, 3.5, 17.2, A.1


  • index, 8.1, 8.1, 8.11, 8.12, 10.2, 10.14, 11, A.2.3


looping with, 9.4, 10.3


  • negative, 8.2


  • slice, 8.4, 10.5


  • starting at zero, 8.1, 10.2



  • infinite loop, 7.3, 7.8, 19.1, A.2.2, A.2.2


  • infinite recursion, 5.10, 5.13, 6.8, A.2.2, A.2.2


  • inheritance, 18.7, 18.10


  • init method, 17.5, 17.10, 18.1, 18.4, 18.7


  • initialization (before update), 7.2


  • instance, 4.1, 4.11, 15.1, 15.8


as argument, 15.2


  • as return value, 15.4



  • instance attribute, 15.2, 15.8, 18.2, 18.10


  • instantiation, 15.1


  • int function, 3.2


  • int type, 2.1


  • integer, 2.11


long, 11.7



  • interactive mode, 1.1, 1.7, 2.4, 3.11


  • interface, 4.6, 4.10, 4.11, 18.9


  • interlocking words, 10.15


  • interpret, 1.1, 1.7


  • invariant, 16.5, 16.6, 19.9


  • invert dictionary, 11.4


  • invocation, 8.8, 8.12


  • is operator, 10.10, 15.6


  • isinstance function, 6.8, 17.8


  • item, 8.12, 10.1


Canvas, 19.3, 19.10


  • dictionary, 11.9



  • item assignment, 8.5, 10.2, 12.1


  • item update, 10.3


  • items method, 12.6


  • iteration, 7, 7.3, 7.8



  • join method, 10.9, 18.5



  • Kangaroo class, 17.12


  • Kevin Bacon Game, 14.12


  • KeyError, 11, A.2.3


  • Koch curve, 5.14


  • key, 11, 11.9


  • key-value pair, 11, 11.9, 12.6


  • keyboard input, 5.11


  • keys method, 11.2


  • keyword, 2.3, 2.3, 2.11, A.1


def, 3.5


  • elif, 5.6


  • else, 5.5



  • keyword argument, 4.5, 4.11, 12.7, 19.2, 19.10



  • Label widget, 19.2


  • Linux, 1.3.4


  • language

formal, 1.4


  • high-level, 1.1


  • low-level, 1.1


  • natural, 1.4


  • programming, 1.1


  • safe, 1.3.2


  • Turing complete, 6.5



  • leap of faith, 6.6


  • len function, 3.15, 8.2, 11


  • letter frequency, 12.11


  • letter rotation, 8.13, 11.10


  • lipogram, 9.2


  • list, 10, 10.9, 10.14, 12.8


as argument, 10.12


  • comprehension, 10.7


  • concatenation, 10.4, 10.12, 10.15


  • copy, 10.5


  • element, 10.2


  • empty, 10.1


  • function, 10.9


  • index, 10.2


  • membership, 10.2


  • method, 10.6


  • nested, 10.1, 10.3


  • of objects, 18.4


  • of tuples, 12.5


  • operation, 10.4


  • repetition, 10.4


  • slice, 10.5


  • traversal, 10.3, 10.14



  • literalness, 1.4


  • local variable, 3.9, 3.14


  • log function, 3.3


  • logarithm, 13.12


  • logical operator, 5.2, 5.3


  • long integer, 11.7


  • lookup, 11.9


  • lookup, dictionary, 11.3


  • loop, 4.2, 4.11, 7.3, 12.5


condition, A.2.2


  • event, 19.1


  • for, 4.2, 8.3, 10.3


  • infinite, 7.3, 19.1, A.2.2


  • nested, 18.4


  • traversal, 8.3


  • while, 7.3



  • looping

with dictionaries, 11.2


  • with indices, 9.4


  • with strings, 8.7



  • looping and counting, 8.7


  • looping with indices, 10.3


  • low-level language, 1.1, 1.7


  • ls (Unix command), 14.8



  • Markov analysis, 13.8


  • McCloskey, Robert, 8.3


  • MD5 algorithm, 14.12


  • Menubutton widget, 19.7


  • Monty Python and the Holy Grail, 16.2


  • MP3, 14.12


  • map pattern, 10.7, 10.14


  • map to, 18.1


  • mapping, 10.2, 10.14, 13.8


  • mash-up, 13.8


  • math function, 3.3


  • max function, 12.3, 12.4


  • membership

bisection search, 10.15


  • dictionary, 11


  • list, 10.2


  • set, 11



  • memo, 11.5, 11.9


  • mental model, A.3.1


  • metaphor, method invocation, 17.2


  • metathesis, 12.11


  • method, 8.8, 8.12, 17.1, 17.11


__cmp__, 18.3


  • __str__, 17.6, 18.5


  • add, 17.7


  • append, 10.6, 10.12, 18.4, 18.6


  • close, 14.2, 14.6, 14.8


  • config, 19.3


  • count, 8.8


  • extend, 10.6


  • get, 11.1


  • init, 17.5, 18.1, 18.4, 18.7


  • items, 12.6


  • join, 10.9, 18.5


  • keys, 11.2


  • mro, 18.9


  • pop, 10.8, 18.6


  • radd, 17.8


  • read, 14.8


  • readline, 9.1, 14.8


  • remove, 10.8


  • replace, 13.1


  • setdefault, 11.4


  • sort, 10.6, 10.13, 12.7, 18.6


  • split, 10.9, 12.2


  • string, 8.13


  • strip, 9.1, 13.1


  • translate, 13.1


  • update, 12.6


  • values, 11


  • void, 10.6



  • method append, 10.15


  • method resolution order, 18.9


  • method syntax, 17.2


  • method, bound, 19.6


  • method, list, 10.6


  • min function, 12.3, 12.4


  • model, mental, A.3.1


  • modifier, 16.3, 16.6


  • module, 3.3, 3.14, 3.14


anydbm, 14.6


  • bisect, 10.15


  • copy, 15.6


  • datetime, 16.7


  • Gui, 19.1


  • HTMLParser, 19.11


  • Image, 19.11


  • os, 14.4


  • pickle, 14.1, 14.7


  • pprint, 11.8


  • profile, 13.9


  • random, 10.15, 12.7, 13.2, 18.6


  • reload, 14.9, A.1.1


  • shelve, 14.7, 14.12


  • string, 13.1


  • structshape, 12.9


  • urllib, 14.12, 19.11


  • Visual, 17.12


  • vpython, 17.12


  • World, 15.9



  • module object, 3.3, 14.9


  • module, writing, 14.9


  • modulus operator, 5.1, 5.13


  • mro method, 18.9


  • multiline string, 4.9, A.1


  • multiple assignment, 7.1, 7.8, 11.6


  • multiplicity (in class diagram), 18.8, 18.10


  • mutability, 8.5, 10.2, 10.5, 10.11, 11.6, 12.1, 12.8, 15.5


  • mutable object, as default value, 17.12



  • NameError, 3.9, A.2.3


  • Newton’s method, 7.5


  • None special value, 3.11, 6.1, 6.10, 10.6, 10.8


  • natural language, 1.4, 1.7


  • negative index, 8.2


  • nested conditional, 5.7, 5.13


  • nested list, 10.1, 10.3, 10.14


  • newline, 5.11, 7.1, 18.5


  • not operator, 5.3


  • number, random, 13.2



  • OverflowError, 5.12


  • object, 8.5, 8.12, 10.10, 10.10, 10.14, 15.1


Callable, 19.7


  • Canvas, 15.9


  • class, 15.1


  • copying, 15.6


  • Event, 19.8


  • embedded, 15.3, 15.8, 17.12


  • file, 9.1, 9.6


  • function, 3.5, 3.15


  • module, 14.9


  • mutable, 15.5


  • printing, 17.2



  • object code, 1.1, 1.7


  • object diagram, 15.2, 15.3, 15.6, 15.8, 16.1, 18.2


  • object-oriented language, 17.11


  • object-oriented programming, 17.1, 17.11, 18.7


  • octal, 2.2


  • odometer, 9.7


  • open function, 9.1, 9.1, 14.2, 14.5, 14.6


  • operand, 2.5, 2.11


  • operator, 2.11


and, 5.3


  • bitwise, 2.5


  • boolean, 8.9


  • bracket, 8.1, 10.2, 12.1


  • comparison, 5.2


  • conditional, 18.3


  • del, 10.8


  • format, 14.3, 14.11, A.2.3


  • in, 8.9, 9.3, 10.2, 11


  • is, 10.10, 15.6


  • logical, 5.2, 5.3


  • modulus, 5.1, 5.13


  • not, 5.3


  • or, 5.3


  • overloading, 17.11


  • slice, 8.4, 8.13, 10.5, 10.12, 12.1


  • string, 2.8


  • update, 10.7



  • operator overloading, 17.7, 18.3


  • operator, arithmetic, 2.5


  • option, 19.2, 19.10


  • optional argument, 8.8, 10.9, 11.3


  • optional parameter, 13.5, 17.5


  • or operator, 5.3


  • order of operations, 2.7, 2.10, A.3.2


  • os module, 14.4


  • other (parameter name), 17.4


  • overloading, 17.11


  • override, 13.5, 13.11, 17.5, 18.3, 18.7, 18.9



  • PEMDAS, 2.7


  • PIL (Python Imaging Library), 19.11


  • Point class, 15.1, 17.5


  • Project Gutenberg, 13.1


  • Puzzler, 9.7, 9.7, 9.7, 11.10, 12.11


  • Pythagorean theorem, 6.2


  • Python 3.0, 1.5, 2.5, 5.11, 11.7, 12.5


  • Python debugger (pdb), A.2.3


  • Python Imaging Library (PIL), 19.11


  • packing widgets, 19.6, 19.10


  • palindrome, 6.11, 8.13, 9.4, 9.7, 9.7


  • parameter, 3.8, 3.9, 3.14, 10.12


gather, 12.4


  • optional, 13.5, 17.5


  • other, 17.4


  • self, 17.2



  • parent class, 18.7, 18.7, 18.10


  • parentheses

argument in, 3.1


  • empty, 3.5, 8.8


  • matching, 1.3.1


  • overriding precedence, 2.7


  • parameters in, 3.8, 3.9


  • parent class in, 18.7


  • tuples in, 12.1



  • parse, 1.4, 1.7, 14.12


  • pass statement, 5.4


  • path, 14.4, 14.11


absolute, 14.4


  • relative, 14.4



  • pattern

DSU, 12.7, 13.4


  • decorate-sort-undecorate, 12.7


  • filter, 10.7, 10.14


  • guardian, 6.8, 6.10, 8.11


  • map, 10.7, 10.14


  • reduce, 10.7, 10.14


  • search, 8.6, 8.12, 9.3, 11.3


  • swap, 12.2



  • pdb (Python debugger), A.2.3


  • permission, file, 14.5


  • persistence, 14.1, 14.11


  • pi, 3.3, 7.9


  • pickle module, 14.1, 14.7


  • pickling, 14.7


  • pie, 4.12


  • pipe, 14.8, 14.12


  • pixel coordinate, 19.8


  • plain text, 9.1, 13.1, 14.12, 19.11


  • planned development, 16.4, 16.6


  • playing card, Anglo-American, 18


  • poetry, 1.4


  • point, mathematical, 15.1


  • poker, 18, 18.11


  • polygon function, 4.3


  • polymorphism, 17.9, 17.11, 18.9


  • pop method, 10.8, 18.6


  • popen function, 14.8


  • portability, 1.1, 1.7


  • postcondition, 4.10, 6.9, 18.9


  • pprint module, 11.8


  • precedence, 2.11, A.3.2


  • precondition, 4.10, 4.11, 4.11, 6.9, 10.15, 18.9


  • prefix, 13.8


  • pretty print, 11.8


  • print statement, 1.5, 1.7, 17.6, A.2.4


  • problem recognition, 9.3, 9.4, 9.6


  • problem solving, 1, 1.7


  • profile module, 13.9


  • program, 1.2, 1.7


  • program testing, 9.5


  • programming language, 1.1


  • prompt, 1.1, 1.7, 5.11


  • prose, 1.4


  • prototype and patch, 16.2, 16.4, 16.6


  • pseudorandom, 13.2, 13.11


  • pure function, 16.2, 16.6


  • python.org, 1.8



  • quotation mark, 1.5, 2.1, 2.1, 4.9, 8.4, A.1



  • Ramanujan, Srinivasa, 7.9


  • Rectangle class, 15.3


  • RSA algorithm, 11.7


  • RuntimeError, 5.10, 6.8


  • radd method, 17.8


  • radian, 3.3


  • rage, A.3.4


  • raise statement, 11.3, 16.5


  • randint function, 10.15, 13.2


  • random function, 12.7, 13.2


  • random module, 10.15, 12.7, 13.2, 18.6


  • random number, 13.2


  • random text, 13.8


  • random walk programming, 13.10, A.3.4


  • rank, 18.1


  • raw_input function, 5.11


  • read method, 14.8


  • readline method, 9.1, 14.8


  • recursion, 5.8, 5.8, 5.13, 6.5, 6.6


base case, 5.9


  • infinite, 5.10, 6.8, A.2.2



  • recursive definition, 6.5, 12.11


  • reduce pattern, 10.7, 10.14


  • reducible word, 11.10, 12.11


  • redundancy, 1.4


  • refactoring, 4.7, 4.7


  • reference, 10.11, 10.12, 10.14


aliasing, 10.11



  • relative path, 14.4, 14.11


  • reload function, 14.9, A.1.1


  • remove method, 10.8


  • repetition, 4.2


list, 10.4



  • replace method, 13.1


  • repr function, 14.10


  • representation, 15.1, 15.3, 18.1


  • return statement, 5.8, 6.1, A.3.3


  • return value, 3.1, 3.14, 6.1, 15.4


tuple, 12.3



  • reverse lookup, dictionary, 11.3, 11.9


  • reverse word pair, 10.15


  • reversed function, 12.8


  • rotation

letters, 11.10



  • rotation, letter, 8.13


  • rules of precedence, 2.7, 2.11


  • running pace, 1.8, 2.12, 16.7


  • runtime error, 1.3.2, 2.10, 5.10, 5.12, A, A.2.3



  • Scrabble, 12.11


  • SimpleTurtleWorld class, 19.6


  • SVG, 19.11


  • Swampy, 4.1, 9.1, 15.9, 18.11, 19.1


  • SyntaxError, 3.4


  • safe language, 1.3.2


  • sanity check, 11.8


  • scaffolding, 6.2, 6.10, 11.8


  • scatter, 12.4, 12.10


  • script, 1.1, 1.7


  • script mode, 1.1, 1.7, 2.4, 3.11


  • search, 11.3


  • search pattern, 8.6, 8.12, 9.3


  • search, bisection, 10.15


  • secret exercise, 14.12


  • self (parameter name), 17.2


  • semantic error, 1.3.3, 1.7, 2.1, 2.10, 8.11, A, A.3


  • semantics, 1.3.3, 1.7, 17.1


  • sequence, 8.1, 8.12, 10.1, 10.9, 12.1, 12.8


coordinate, 19.4



  • set, 13.6


anagram, 12.11, 14.7



  • set membership, 11


  • setdefault method, 11.4


  • sexagesimal, 16.4


  • shallow copy, 15.6, 15.8


  • shape, 12.10


  • shape error, 12.9


  • shell, 14.8


  • shelve module, 14.7, 14.12


  • shuffle function, 18.6


  • sine function, 3.3


  • singleton, 11.4, 11.9, 12.1


  • slice, 8.12


copy, 8.4, 10.5


  • list, 10.5


  • string, 8.4


  • tuple, 12.1


  • update, 10.5



  • slice operator, 8.4, 8.13, 10.5, 10.12, 12.1


  • sort method, 10.6, 10.13, 12.7, 18.6


  • sorted function, 12.8


  • source code, 1.1, 1.7


  • special case, 9.5, 9.6, 16.3


  • special value

False, 5.2


  • None, 3.11, 6.1, 6.10, 10.6, 10.8


  • True, 5.2



  • split method, 10.9, 12.2


  • sqrt, 6.2


  • sqrt function, 3.3


  • square root, 7.5


  • squiggly bracket, 11


  • stack diagram, 3.10, 3.10, 3.14, 4.12, 5.9, 6.5, 6.11, 10.12


  • state diagram, 2.2, 2.11, 7.1, 8.11, 10.2, 10.10, 10.11, 11.4, 12.6, 15.2, 15.3, 15.6, 16.1, 18.2


  • statement, 2.4, 2.11


assert, 16.5


  • assignment, 2.2, 7.1


  • break, 7.4


  • compound, 5.4


  • conditional, 5.4, 5.13, 6.4


  • for, 4.2, 8.3, 10.3


  • global, 11.6


  • if, 5.4


  • import, 3.14, 4.1, 14.9


  • pass, 5.4


  • print, 1.5, 1.7, 17.6, A.2.4


  • raise, 11.3, 16.5


  • return, 5.8, 6.1, A.3.3


  • try, 14.5


  • while, 7.3



  • step size, 8.13


  • str function, 3.2


  • __str__ method, 17.6, 18.5


  • string, 2.1, 2.11, 10.9, 12.8


accumulator, 18.5


  • comparison, 8.10


  • empty, 10.9


  • immutable, 8.5


  • method, 8.8


  • multiline, 4.9, A.1


  • operation, 2.8


  • slice, 8.4


  • triple-quoted, 4.9



  • string method, 8.13


  • string module, 13.1


  • string representation, 14.10, 17.6


  • string type, 2.1


  • strip method, 9.1, 13.1


  • structshape module, 12.9


  • structure, 1.4


  • subclass, 18.7


  • subject, 17.2, 17.11, 19.6


  • subtraction

dictionary, 13.6


  • with borrowing, 7.6



  • subtraction with borrowing, 16.4


  • suffix, 13.8


  • suit, 18.1


  • sum function, 12.4


  • superclass, 18.7


  • superstitious debugging, A.3.4


  • swap pattern, 12.2


  • syntax, 1.3.1, 1.3.1, 1.7, 17.1, A.1


  • syntax error, 1.3.1, 1.7, 2.10, A



  • Tagger, 18.11


  • Text widget, 19.5


  • Time class, 16.1


  • Tkinter, 19.1


  • True special value, 5.2


  • Turing complete language, 6.5


  • Turing Thesis, 6.5


  • Turing, Alan, 6.5


  • TurtleWorld, 4.1, 5.14, 18.11


  • TypeError, 8.1, 8.5, 11.4, 12.1, 12.4, 14.3, 17.3, A.2.3


  • temporary variable, 6.1, 6.10, A.3.2


  • test case, minimal, A.2.4


  • testing

and absence of bugs, 9.5


  • incremental development, 6.2


  • interactive mode, 1.1


  • is hard, 9.5


  • knowing the answer, 6.2


  • leap of faith, 6.6


  • minimal test case, A.2.4



  • text

plain, 9.1, 13.1, 14.12, 19.11


  • random, 13.8



  • text file, 14.11


  • token, 1.4, 1.7


  • traceback, 3.10, 3.14, 5.10, 5.12, 11.3, A.2.3


  • translate method, 13.1


  • traversal, 8.3, 8.3, 8.6, 8.11, 8.12, 9.3, 9.3, 10.7, 10.14, 11.1, 11.2, 12.5, 12.5, 12.7, 13.3


dictionary, 17.10


  • list, 10.3



  • traverse

dictionary, 12.6



  • triangle, 5.14


  • trigonometric function, 3.3


  • triple-quoted string, 4.9


  • try statement, 14.5


  • tuple, 12.1, 12.3, 12.8, 12.10


as key in dictionary, 12.6, 13.9


  • assignment, 12.2


  • comparison, 12.7, 18.3


  • in brackets, 12.6


  • singleton, 12.1


  • slice, 12.1



  • tuple assignment, 12.3, 12.5, 12.10


  • tuple function, 12.1


  • turtle typewriter, 4.12


  • type, 2.1, 2.1, 2.11


bool, 5.2


  • dict, 11


  • file, 14


  • float, 2.1


  • int, 2.1


  • list, 10


  • long, 11.7


  • set, 13.6


  • str, 2.1


  • tuple, 12.1


  • user-defined, 15.1, 16.1



  • type checking, 6.8


  • type conversion, 3.2


  • type function, 15.7


  • type-based dispatch, 17.8, 17.9, 17.11


  • typewriter, turtle, 4.12


  • typographical error, 13.10



  • UML, 18.8


  • UnboundLocalError, 11.6


  • Unix command

gzip, 14.8


  • ls, 14.8



  • URL, 14.12, 19.11


  • underscore character, 2.3


  • uniqueness, 10.15


  • update, 7.2, 7.5, 7.8


coordinate, 19.8


  • database, 14.6


  • global variable, 11.6


  • histogram, 13.3


  • item, 10.3


  • slice, 10.5



  • update method, 12.6


  • update operator, 10.7


  • urllib module, 14.12, 19.11


  • use before def, 2.10, 3.6


  • user-defined type, 15.1, 16.1



  • ValueError, 5.11, 11.3, 12.2


  • Visual module, 17.12


  • value, 2.1, 2.11, 10.10, 10.10, 11.9


default, 13.5


  • tuple, 12.3



  • values method, 11


  • variable, 2.2, 2.11


global, 11.6


  • local, 3.9


  • temporary, 6.1, 6.10, A.3.2


  • updating, 7.2



  • variable-length argument tuple, 12.4


  • vector graphics, 19.11


  • veneer, 18.6, 18.10


  • void function, 3.11, 3.14


  • void method, 10.6


  • vpython module, 17.12



  • World module, 15.9


  • walk, directory, 14.4


  • while loop, 7.3


  • whitespace, 3.13, 5.12, 9.1, 14.10, A.1


  • widget, 19.1, 19.10


Button, 19.2


  • Canvas, 19.3


  • Entry, 19.5


  • Frame, 19.6


  • Label, 19.2


  • Menubutton, 19.7


  • Text, 19.5



  • widget, packing, 19.6


  • word count, 14.9


  • word frequency, 13.1, 13.12


  • word, reducible, 11.10, 12.11


  • working directory, 14.4


  • worst bug, 17.12


ever, 19.11




  • Zipf’s law, 13.12


  • zero, index starting at, 8.1, 10.2


  • zip function, 12.5


use with dict, 12.6



Retrieved from 'https://en.wikibooks.org/w/index.php?title=Think_Python/Print_version&oldid=3142392'