Programming in Python 3 (Second Edition)


ISBN-10: 0321680561 – ISBN-13: 978-0321680563

This book covers Python 3.0 and 3.1 and should work with all Python 3.x versions. After reading the book we recommend reading the “What's New in Python” documents for 3.2, 3.3, etc., to learn about new features and improvements that have been made since the book was published.

Second Edition: Errata for Second Printing

Issue Resolution Reporter
Pages 495 and 499. Factual error. I have been persuaded that the footnote on page 495 is wrong and that backreferences do not work inside character classes. The example at the start of page 499 does work but only by serendipity. In particular, [^\1>] can be replaced with [^>] without changing the semantics. One possible solution for matching the same quote is to use negative lookahead; see for example, this answer on stackoverflow. Alexey Zinger

Second Edition: Errata for All Printings

Issue Resolution Reporter
Page 21. Factual error. In the second paragraph replace "and remove() which removes an item at a given index position." with "and remove() which removes the given item." Later references to the list.remove() method are correct. Daniel Wójcik
Page 61. Naïve floating-point comparison. The equal_float() function shown on this page is simple and standard, but it doesn't work well when the numbers compared have very different magnitudes. Here's an improved version:

def equal_float(a, b):
    return abs(a - b) <= (sys.float_info.epsilon * min(abs(a), abs(b)))
The examples' Util module has an equal_float() function that takes an optional third argument—the number of decimal places to compare to.
William Jones
Page 68. Mistake re `ä' ordering. The second from last paragraph says that in German `ä' is sorted as if spelled `æ': this should be qualified since it is only true of German phonebooks; in German dictionaries it is sorted as plain `a'. Jasmin Blanchette
Page 73. Incorrect method description. Change the last three words in table 2.8's s.isdigit() description to “a Unicode digit”. Ross Burnett
Page 83. Duplicate word. The last sentence of the first paragraph of the Format Specifications subsection begins “The the”—this should simply be “The”. Michael Bernt
Page 134. Code error in the text. In the second paragraph (immediately after the greens example), I say: "Here, using mapping unpacking (**) has exactly the same effect as writing .format(, olive=greens.olive, lime=greens.lime)". That would be true if greens was an object with those attributes, but in fact it is simply a dict with those keys, so the correct code is: .format(green=greens["green"], olive=greens["olive"], lime=greens["lime"]). Clemens Kaposi
Page 144. Wrong word. The first line on this page contains the phrase "a number that cannot be less than"; change "less" to "more" to correct the meaning. Iama Netizen
Page 202. Subtle code error. The relative import shown in the right hand code snippet is incorrect—but unfortunately, due to a bug in Python 3.0.0–3.1.2, it actually works. It doesn't work from Python 3.1.3 though, so should be replaced with from .. import Png (which means import the Png module from the module two directories—because there are two dots—above this one, i.e., from the Graphics module). This correction has been applied to the downloadable archives. Author
Page 215. Additional note. The optparse module discussed here is deprecated in Python 3.2; it has been superceded by the argparse module. The book's examples continue to use optparse so that they work with all Python 3.x versions. Stick with optparse if you need to maintain backward compatibility with Python 3.1; otherwise switch to argparse which is better (and easy to switch to). Jim Johnston
Page 235. Spurious word. In the section “Object-Oriented Concepts and Terminology”'s first paragraph's third sentence, replace the phrase “data type in later in this section,” with “data type later in this section,” Joshua Lusk
Page 238. Typo. The last sentence should end “is shown here:”, not “is show here:”. Binshuo Hu
Pages 270–275. Subtle bug. The module (and various alternative versions such as, have a subtle bug that causes incorrect behavior if the key function folds case (e.g., lambda x: x.lower()) and there are multiple values which have the same keys (e.g., "abc" and "ABC"). The algorithms used in the methods shown in the book are correct, but many of the methods must be changed to account for this use case. The necessary corrections have been applied to the downloadable archives. Kahn Fusion
Page 377. Subtle code and explanation error. Replace the penultimate paragraph's last sentence (beginning "It stores the setter method"), with
"It stores the setter method it has been given (which can now be used in the __set__() method), and returns the descriptor itself, since it is the descriptor through which the instance data is accessed."
Also, replace the last line of the setter() method (return self.__setter) with return self.
Luca Boasso
Page 481. SQLite syntax variation. The SQLite SQL used to create the tables shown on this page uses the keyword AUTOINCREMENT. For some versions of SQLite this keyword is a syntax error. If this is the case for your version of SQLite simply delete the keyword—you will still get autoincrementing since for versions of SQLite that don't accept AUTOINCREMENT, the use of INTEGER PRIMARY KEY implies autoincrement. Florian Rämisch
Pages 534–553. PyParsing update. The book uses PyParsing version 1.5.2 which was current at the time of writing. Version 1.5.5 has introduced some changes—for example, the module is now pyparsing for both Python 2 and Python 3 (before it was pyparsing_py3 for Python 3). The other changes are bug fixes, enhancements, and additional examples, so apart from the import, everything in the book remains valid. Author

Second Edition: Errata for the First Printing only (additional to the errata above—these are all fixed in the Second and subsequent printings)

Issue Resolution Reporter
Page 34. Incorrect output. At the bottom of the page, change each occurrence of "number" in the output to "integer". Algis Kabaila
Pages 89 & 95. Update to footnote info. The footnotes on these pages point out the Window's console's poor UTF-8 support and notes that alternative examples ( and are provided to work around this. Now Glenn Linderman has found a solution (that I've tested successfully with Python 3.1); see Python Bug 1602/message #94445. If the solution is followed, Windows users can use the same and programs as Linux and Mac OS X users and see the same characters output. (Be aware though, that this may cause problems executing other programs in the console, so for anything else it is probably best to use a separate console.) Author
Page 90. Bug fix. The print_unicode() function has a subtle bug. Replace the line:
    end = sys.maxunicode
with the line:
    end = min(0xD800, sys.maxunicode) # Stop at surrogate pairs
This is because Python can't handle surrogate pairs and some of them start at code point U+D800. This correction has been applied to the downloadable archives.
Hugo Gagnon
Page 258. Clarification. In the description of the reimplementation of the __repr__() method I say that it is necessary to call super().__repr__() to access the base class's __repr__() method without causing infinite recursion. That reason is true in general, but not in this particular case. Nonetheless, the code shown is correct. What I should have said is this:
"For the str.format()'s second argument we cannot just pass self. There are two reasons for this. First, if we use self, Python will format it using the __str__() method if that is present in this class or (as in this case) in one of its base classes, whereas we want the representational format rather than the string format. And second, if there is no __str__() implementation, Python will fall back to using __repr__(), thus leading to infinite recursion. By calling the base class's __repr__() method we ensure that we get the representational format and at the same time avoid depending on whether or not a __str__() method happens to be implemented."
Luca Boasso
Page 454. Incorrect URL. In the second paragraph, change the URL to Takahiro Nagao