Programming in Python 3 (First Edition)


ISBN-10: 0137129297 – ISBN-13: 978-0137129294

This book has been superceded by Programming in Python 3: A Complete Introduction to the Python Language (Second Edition).

First Edition: Errata for All Printings

Issue Resolution Reporter
Page 21. Clarification. The book shows the following interactive session:

>>> a = "many paths"
>>> b = "many paths"
>>> a is b

In some cases, comparing the identity of two strings or numbers, even if assigned separately as shown here, will return True. This is because some implementations of Python will reuse the same object (since the value is the same and is immutable), for the sake of efficiency. Of course, this is a reminder to compare values using == and !=, and to only use is and is not when comparing with None or when you really do want to see if two object references, rather than their values, are the same.
Robert Lummis; Leon Matthews
Page 54. Python 3.1 difference. The floating-point number output shown on this page is different between Python 3.0 and 3.1. This is because 3.1 uses a smarter algorithm for displaying floating-point numbers that shows as few digits as possible without loss of accuracy. Note though, that internally, Python—like practically every other language—stores most floating-point numbers as approximations, so the tiny amount of inaccuracy is still there, just less obvious. Alexis Layton
Page 56. Incorrect word. In Table 2.5's entry for math.floor(), replace "smallest" with "largest". Benjamin Fischer
Page 57. Erroneous table entry. In Table 2.6, delete the math.sum() entry, and in the index delete the math.sum() and sum() (math) entries. (The correct function is math.fsum() which is listed in Table 2.5, and is in the index.) Ihar Hrachyshka
Page 66. Slightly misleading explanation. The third paragraph describes the two colon slicing plus striding syntax, and says that you cannot omit the step—it should have said that you can omit it, but there's no point doing so. This is because if you omit the step, it defaults to 1, but that's the default anyway, so for a step size of 1, the one colon syntax is sufficient. Tom Zych
Page 71. Incorrect code. The code snippet at the bottom right of the page should have the line result = "", "", s not result = s, "", "". Takahiro Nagao
Pages 82 & 88. Error in footnotes on both pages regarding on Mac. The footnote on each of these pages says that Mac uses the Apple Roman encoding in and therefore cannot output all the Unicode characters. This is incorrect—happily the Mac uses UTF-8 and both the and examples work fine on the Mac. (I made the mistake because I tested them on the Mac by running the book's test suite—which runs tests using the subprocess module—rather than directly at the console, and subprocess seems to use the Apple Roman encoding on Mac.) Author
Page 94. Converting the text to HTML and truncating it has a subtle bug. The code at the top of this page truncates HTML-escaped text, which means it might erroneously cut off the end of an HTML entity. Replace the top 6 lines with these 5 lines:

    if len(field) <= maxwidth:
	field = escape_html(field)
	field = "{0} ...".format(escape_html(field[:maxwidth]))

Note also, that the single line of code quoted in the middle of the page suffers from the same problem and should be replaced with: print("<td>{0}</td>".format(escape_html(field[:maxwidth]))).
(If you are using Python 3.1 or later you can use {} instead of {0} throughout.)
Peter Bray
Page 117. Error regarding comparison operators. The last paragraph says that dictionaries can be compared with <, <=, ==, !=, >=, and >. This was true in Python 2, but is (fortunately) not the case in Python 3 where only == and != are supported. Jennifer Lindner
Page 121. Incorrect word. In the second paragraph's second sentence, beginning "And we can use the union operator", replace "union" with "intersection". Benjamin Fischer
Page 136. Incorrect number. In the paragraph immediately above the Copying Collections subsubsection, the returned list should start with -7.5 not -7.3. Benjamin Fischer
Page 144. The calculate_mode() function works correctly but is needlessly complicated. The calculate_mode() function only ever deals with integers, so it can be simplified. Change the list comprehension's if condition from math.fabs(frequency - highest_frequency) <= sys.float_info.epsilon to frequency == highest_frequency. This change also affects the text, so replace the second sentence in the second paragraph that follows the code snippet (the one starting "Since the numbers may be floating-point"), with "We can compare using operator == since all the frequencies are integers." Tim Pietzcker
Page 152. Slightly misleading description of using return in a for loop. Replace the last sentence of the penultimate paragraph—the paragraph begins "If a continue", and the sentence to replace begins "If the loop is broken"—with:
"If the loop is broken out of due to a break statement, or a return statement (if the loop is in a function or method), or if an exception is raised, the else clause's suite is not executed. (If an exception occurs, Python skips the else clause and looks for a suitable exception handler—this is covered in the next section.)"
Peter Bray
Page 157. Incorrect exception mentioned. In the second paragraph the exception mentioned should be UnicodeDecodeError, not ValueError Takahiro Nagao
Page 168. Wrong units of measurement. For the heron2() function the units of measurement should be "square meters" and "square inches" (not plain meters and inches). Peter Bray
Page 205. Incorrect word. In the first paragraph change --width to --maxwidth (twice). Takahiro Nagao
Page 231. Subtle incompleteness. The third paragraph from the bottom says that custom classes support == by default and that the comparison always returns False. There is in fact one case where the comparison returns True—when a custom object is compared with itself. Alexis Layton
Page 296. Incorrect class name. In the first and second paragraphs, change textwrap.TextWrap to textwrap.TextWrapper. Takahiro Nagao
Pages 398 & 399. Localization issue. The code at the bottom of page 398 and the first line of code on page 399 may not work in all locales. This is because the subprocess module always uses binary data but encodes/decodes using the local encoding—this has been reported as bug 6135 and should be fixed in due course. If you get burnt by this the solution is to set sys.stdin to binary mode and do the decoding yourself. For all Python 3.x versions this can be done by reading the data with data =; and for Python 3.1 and later it can be done by sys.stdin = sys.stdin.detach(), and then doing data =—and in either case, decoding data, e.g., lines = data.decode("utf8").splitlines(). Takahiro Nagao
Page 409. Incorrect URL. In the fourth paragraph, change the URL to Takahiro Nagao
Pages 421 & 422; an explicit context manager is not needed for gzip with Python 3.1. From Python 3.1, gzip.GzipFile supports the context manager protocol so it is not necessary to use contextlib.closing() or a custom context manager when handling a gzip file handle with Python 3.1—unless you want backward compatibility with Python 3.0. The techniques shown are still valid though, e.g., for classes that don't support the context manager protocol, and of course for programs that must support gzip for all Python 3.x versions. Author
Page 434. Subtle bug. The find_dvd() function has a subtle bug. The fix is to replace the enumerate() line with these lines:
    matches = sorted(matches, key=str.lower)
    for i, match in enumerate(matches):
Takahiro Nagao
Pages 461 & 462; typos. Change every occurrence of "W." to "W" (e.g., in the name "James W Loewen")—or, alternatively, change the regex on page 459 to:
    name = re.sub(r"(?P<forenames>\w+\.?(?:\s+\w+\.?)*)\s+(?P<surname>\w+)",
                  r"\g<surname>, \g<forenames>", name)
Peter Bray

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

Issue Resolution Reporter
Page 4. Package names and availability are not as stated. Only two installers appear to be available for Windows, a generic one (x86) and an AMD64-specific one; use the generic one unless you are sure you have an AMD64 processor. Fedora 10 does not have Python 3 packages after all, so you must manually build from the sources. Ubuntu 8 does have Python 3 packages—their names are python3.0 for Python 3, idle-python3.0 for IDLE, and python3.0-doc for the documentation. Author
Page 5. Executable names are not as stated. The Python executable is called python3.0 (or python3.1 depending on which version you installed) and IDLE is called idle. In the book the names used throughout are python3 and idle3 to stand for whatever the actual names are (and of course you could alias or soft link to make these names work—in fact, some packages do this for you). Author