Errata

Learning Python

Errata for Learning Python, Fourth Edition

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Printed
Page N/A
N/A

Note from the author:

I keep a separate errata list, which may or may
not intersect with the list kept here over time.
Please see the following web page for my errata
and updates lists:

http://www.rmi.net/~lutz/lp4e-updates.html

Thanks,
--Mark Lutz

Mark Lutz
 
Oct 28, 2009 
Printed
Page N/A
N/A

Note from author:

I plan to copy updates from my own web site to the list here whenever I'm informed of a pending reprint, but for more recent updates, as well as an informal "blog" discussing book-related issues such as Python changes and complexity, book paper choices, and other topics that may vary over time, please see my site's updates page:

http://www.rmi.net/~lutz/lp4e-updates.html

--Mark Lutz

Mark Lutz
 
Nov 30, 2009 
PDF
Page N/A
N/A

This an errata about O'Reilly's errata system (a meta-errata?).

O'Reilly's errata tracking system (this site) strips whitespace in program code that is posted to it. Unfortunately, because whitespace is signicant to the left of code in Python, and a required part of Python syntax, some of the code posted here is not correct.

For instance, the "def" and "class" statements in posts here are invalid as shown, and you'll have to infer the correct indentation from their content. Less harmful but still painful, space has been stripped before "#" comments, leading to very unreadable code. Not exactly a Python-friendly interface.

I've asked O'Reilly to look into this; for now, when in doubt please refer to the correctly presented code on my website:

http://www.rmi.net/~lutz/lp4e-updates.html

(This may also be an issue for PDF files generated by O'Reilly for Python titles: it appears that whitespace does not survive cut-and-paste of code. This is TBD, pending a review by O'Reilly.)

--Mark Lutz

Mark Lutz
 
Nov 30, 2009 
Printed, PDF, , Other Digital Version
Page n/a
n/a

[No fix required -- informational only]

I've posted supplemental notes about a number of advanced and somewhat obscure language topics, including super(), mro(), __new__, and packages at my own book clarifications page:

http://www.rmi.net/~lutz/lp4e-updates.html

Book inserts for these (if any) are posted as separate errata entries elsewhere on this list.

Mark Lutz
 
May 21, 2011 
, Printed, PDF, , Other Digital Version
Page n/a
examples using Python's input() built-in in 3.2.0 on Windows

[No fix required] A reader reported this issue for Programming Python scripts which use input(), but also noted its appearance in some Learning Python examples. This reflects a bug in Python 3.2.0, not in the book's examples. Please see:

http://www.rmi.net/~lutz/lp4e-updates-notes-recent.html#py320inputbug

for details. In short, Python's input() built-in is broken in 3.2.0 (3.2) when used in Windows console mode only. Any script that uses input() in this version and context may fail. This built-in has been fixed in later Python releases. The quickest fix is to upgrade to 3.2.1 or later, or try a different environment; examples in the book which use input() work fine in all other Python versions and in most other contexts such as IDLE.

Mark Lutz
 
Jan 04, 2012 
Printed, PDF, ePub, Mobi, , Other Digital Version
Page n/a
Table 11-1 Explanation: Extended sequence unpacking

For the example shown in Table 11-1, where:
a, *b = 'spam'

The author says the following: "a is assigned 's', and b is assigned 'pam'.

In fact, b is assigned ['p', 'a', 'm']

>>> a, *b = 'spam'
>>> a
's'
>>> b
['p', 'a', 'm']
>>>

Note from the Author or Editor:
Also posted to the errata list of the 5th Edition, which inherits the same issue. This is a valid point, worth patching in both editions, though the description here is intentionally informal, and the accurate output of this code is shown by explicit example later in this section.

See the 5th edition's errata list for the patch; this is on page 283 of the 4th edition, and page 341 of the 5th edition.

Elizabeth Ramirez  Jun 28, 2013 
Printed
Page xxxvii
line 16 of table P-2

[Oct-28-09] Page xxxvii, missing underscore in __index__

On line 16 of table P-2 on this page, "_index__" should be "__index__", with two leading underscores. This was a bad last-minute insert on my part.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 27, 534
see description for two locations to augment

Sep-29-10] Page 27 and 534, note "magic" version number check for byte-code recompiles

1) On page 27, at the very end of the 2nd paragraph that begins "Python saves", add this sentence: "Imports also check to see if the file must be recompiled because it was created by a different Python version, using a "magic" number in the byte-code file itself."

2) Also, on page 534, at the very end of the second to last paragraph which begins "Python checks", add another sentence: "As noted in Chapter 2, imports also recreate byte code if its "magic" Python version number does not match."

Discussion: Technically, in order to know if a recompile is required, imports check both source/bytecode timestamps as well as the bytecode file's internal version/implementation "magic" number The book describes the timestamp check because it's fundamental to all users, but does not go into further detail about the extra magic number test because this is arguably more low-level and detailed than most Pyton newcomers using a single Python require. It becomes more important to know once you start installing new or alternative Pythons, of course, though it would be difficult to imagine how an incompatible Python could work at all without such a mechanism.

[from http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html]

Mark Lutz
 
Sep 29, 2010  Jan 01, 2011
Printed
Page 37
first line of the second-last paragraph

[Nov-11-09] Page 37, "fist line" should be "first line" (minor typo)

In the first line of the second-last paragraph on this page, "fist line" should be "first line", of course. This is in text added for this edition, but the typo wasn't noticed by anybody who read this before publication (including me!).

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 39
start of the 3rd paragraph

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 39, paragraph 3, minor typo: delete extra word "of"

At the start of the 3rd paragraph, change "For instance, of the following tests" to "For instance, the following tests". (This was read many times by many readers, but missed by us all.)

Mark Lutz
 
Jul 12, 2010  Aug 01, 2010
Printed
Page 48
second code listing section

[Dec-8-09] Page 48, last output line missing in example at top of page

In the second code listing section on page 48, the program output should include a 4th line "Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!" after the last line "1267650600228229401496703205376". This was apparently another bad cut-and-paste on my part. The correct, full output of this script is shown in five other places in this chapter (pages 43, 44 (twice), 49, and 51), so most readers should be able to work past this, but its output here may confuse if not patched in reprints.

The correct second code listing on this page should look like this -- the last line is what to add:

C:\misc> c:\python30\python script1.py
win32
1267650600228229401496703205376
Spam!Spam!Spam!Spam!Spam!Spam!Spam!Spam!

--------
This entry was crossposted from the following website:
http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 08, 2009  Jan 01, 2010
Printed, PDF,
Page 58
end of paragraph 2 in the note box

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 58: exec() sentence broken by rewording applied during production

On page 58, at the very end of paragraph 2 in the note box near top of page, change "For more on the 3.0 exec form, see Chapter 9." to read "For more on the file interfaces used by the 3.0 exec form, see Chapter 9."

This was implied in the original admittedly choppy version of this sentence that I submitted (yet another case of copyediting being a bit too aggressive, I'm afraid). Perhaps obvious to many (Chapter 9 covers files, not exec()) but I found myself searching for exec() in Chapter 9 a year later due to the unfortunate rewording of this sentence made during production.

Mark Lutz
 
Jul 12, 2010  Aug 01, 2010
, Printed, PDF, , Other Digital Version
Page 59
Chapter 3, "Using exec to Run Module Files", Comment in last code example

The last code example in this section has the line

...same outout...

It should read

...same output...

Note from the Author or Editor:
Yes (typing too fast, apparently). This is an informal comment and not code, so it isn't too grievous, but it merits a patch in reprints.

Eric Schley  Dec 21, 2010  May 20, 2011
Printed
Page 59
middle of last line of first paragraph on this page

[Dec-14-09] Page 59, middle of last line of first paragraph, "C:Python26" missing a "\" (minor typo)

A directory path is missing a first backslash here (perhaps obvious from many other examples in this section, but worth a fix). Change "C:Python26\Lib\idlelib" to "C:\Python26\Lib\idlelib"

--------
Crossposted from http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 14, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 72
line 6 from top

[Nov-5-10] Page 72, line 6: "PyPy" should be "PyPI" (minor typo)

The title says it all; this sentence refers to the Python Package Index site (PyPI), not the Python in Python project (PyPy). Both are described earlier in the book so this should be obvious to most readers, but it still merits a patch in reprints.

Mark Lutz
 
Nov 05, 2010  Jan 01, 2011
PDF
Page 81
last code example

There is a quote mark missing

>>> S
Spam'
>>> S + 'xyz' # Concatenation

the second line should be 'Spam'
minor typo

Note from the Author or Editor:
Yes -- Spam' should be 'Spam' here, with the leading quote. This is heavily implied by the other examples in this section, and is in interpreter output not user entered code, but merits a patch. (The quote was present in the 3rd Edition, but was dropped in the files I was given as a starting point for work on the 4th Edition; looks like a format converter gone bad...)

Also posted at my errata page:

http://www.rmi.net/~lutz/lp4e-updates.html

Gavin Bell
Gavin Bell
 
Nov 03, 2009  Jan 01, 2010
Printed
Page 81
line 2 of the very last code listing on this page

[Nov-03-09] Page 81, missing quote in interactive session output, lost in conversion

On line 2 of the very last code listing on this page "Spam'" should be "'Spam'", with the leading quote. This is heavily implied by the other examples in this section, and is in interpreter output not user entered code, but merits a patch. (The quote was present in the 3rd Edition, but was dropped in the files I was given as a starting point for work on the 4th Edition; looks like a format converter gone bad...)

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 86
paragraph 3

[Oct-28-09] Page 86, mention XML parsing in types intro chapter 4

In paragraph 3 on this page, I want to mention XML parsing at the end of the strings introduction. Change "even more advanced language processing, including natural language processing." to read "even more advanced text and language processing, including XML parsing and natural language analysis.".

XML parsing is mentioned in the intro section of the in-depth string chapter 7 along with a forward link to XML examples in Chapter 36, so this is perhaps nitpicking; an XML teaser here is warranted, though.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 87
last code listing section, near middle of page

The display of the multiline string literal's value here should start with a blank space, not a '\n' newline character, because the string's literal starts with such (and not an immediate line break).

To fix, in this listing:
>>> msg = """ aaaaaaaaaaaaa
bbb'''bbbbbbbbbb""bbbbbbb'bbbb
cccccccccccccc"""
>>> msg
'\naaaaaaaaaaaaa\nbbb\'\'\'bbbbbbbbbb""bbbbbbb\'bbbb\ncccccccccccccc'

Change the start of the last line:
'\naaaa

To the following (replacing just "\n" with " "):
' aaaa

Mark Lutz
 
Oct 01, 2012  Oct 12, 2012
Printed
Page 90
first code listing on this page

[Nov-03-09] Page 90, generators and iteration protocol: iter() optional

The first code listing on this page shows a generator expression, and a valid but intentionally abbreviated exploration of applying the iteration protocol to it. As suggested briefly later in this chapter and explained more completely later in the book, the full realization of the iteration protocol here would be: G = (...); I = iter(G); and next(I) until StopIteration is raised. Because generators are their own iterator (that is, iter(G) returns G itself), the code on this page is able to skip the iter(G) call and proceed to next(G). This is all explained in-depth later in the book, and this chapter is explicitly designed to be an incomplete first look (like much in this chapter, the full story on iteration is far too subtle for a first pass over built-in types).

Still, this example might seem to contradict the iterator protocol description later in this chapter on first glance. To avoid some confusion, on the second line of page 90 (the code line that reads ">>> next(G)"), add a comment near the end of this line that reads "# iter(G) not required here", where the "#" in this lines up vertically with the "#" of the preceding line. That is, the first two lines on this page should look like:

>>> G = (sum(row) for row in M) # Create a generator of row sums
>>> next(G) # iter(G) not required here

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 90
second line on page, comment

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[May-1-10] {first reprint} Page 90, second line on page, comment font (minor formatting)

The comment text "# iter(G) not required here" should be in italics, like the others are. This comment was added as a patch in the first reprint. It is not present in earlier printings.

(This item and a handful of others in this list labeled as "{first reprint}" were introduced when fixes for prior errata were applied in the first reprint. Patching is a net improvement, but regrettably, fixing errata can itself introduce new errata, so the benefit has to be weighed against the potential risk, especially if the fix involves changing program code.)

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed
Page 91
the very end of the last paragraph before heading "Nesting Revisited"

[Nov-08-09] Page 91, mention the dict(name=val) form in intro chapter

On page 91, at the very end of the last paragraph before heading "Nesting Revisited", add the following sentence: "As we'll learn later, dictionaries may also be made by passing keyword arguments to the type name: dict(name='Bob', job='dev', age=40) makes the same dictionary.", where the "dict(...)" part in this is code in fixed-width font. [Reprints: it looks like there is space for the insert, but please ask me how to shorten if not.]

A related page 186 insert is described ahead. I'm adding this because the dict() call isn't formally described until the list/dict chapter on pages 208 and 217, but pops up in a few examples shortly before that--in some new str.format() calls on pages 186-189. In fact, I would mark this unnoted forward reference as an error (other forward references usually say they are), except that its usage is probably apparent to most readers; it does get covered just 20 pages later; and because of the general book-wide principles concerning forward references which are described in the general book notes section of my book updates webpage noted below. In short, some topics are postponed until later, largely due to Python's design.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 98
last code listing on this page

[Nov-03-09] Page 98, binary file intro example: assumes a file exists

The last code listing on this page opens and reads a file named 'data.bin'. For the purposes of this introductory overview chapter on types, it assumes this file exists, but does not explicitly create it to avoid getting too deep into the 3.0 bytes topic (i.e., it's a deliberately partial example like much in this chapter). If you are working along with the examples here, though, note that this code (and its elaboration on page 234) won't work unless you've already created the binary data file in your working directory; to see how to do so, watch for the more in-depth files coverage of Chapter 9 and 36.

To minimize confusion, though, we'll add the following text at the very end of the last paragraph on page 98, just before the colon there: "(the following partial example assumes there is already a binary file in your current directory)". [Reprints: omit "partial example" if this doesn't fit.]

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 110
4th bullet point from the bottom

"X < Y < Z produces the same result as X < Y and Y < X" should read "X < Y < Z produces the same result as X < Y and Y < Z"

Note from the Author or Editor:
Yes, this is a true typo and should be fixed exactly as described.

The behavior of X < Y < Z is described correctly later in this chapter, at the location referenced in the place where the typo occurs, so hopefully most readers will flip ahead if confused. Still, this merits a reprint patch.

Rial Juan  Mar 29, 2010  Aug 01, 2010
Printed
Page 122
last line of page

The output tuple ('0100', '0x40, '0b1000000'). Shouldn't the first Octal literal be be '0o100'?

The printed value in the book is correct for Python 2.6, but not 3.1.1

Note from the Author or Editor:
Yes, you're right--this should be changed to 0o100.

The new 3.X format for octals is described in depth in this section, but this specific example was run under 2.6; since the rest of the book is "3.X unless stated otherwise", this should be patched in reprints. Oddly, another 2.6 item snuck in on the next page (an already-posted errata); these were probably run at the same time.

Anonymous  Jan 25, 2010  Jan 01, 2011
Printed
Page 123
the last code listing on page 123

[Nov-03-09] Page 123, three numeric tests: run under 2.X not 3.X

I ran the last code listing on page 123 (along with its continuation on the next page) under Python 2.6 on purpose, in order to show the long precision used for large integers. This should be obvious given the discussion of the "L" suffix for 2.6 longs earlier in the chapter. I didn't explicitly state that this example gives 2.6 output format, though, and that may confuse, given that other examples are either 3.X or labeled as 2.X.

To clarify, at the end of the last paragraph on page 123 and just before that page's last code listing, add "(run in 2.6 here to reveal the long precision)" just before the colon there.

For reference (not to be placed in the book), here's how this looks if run in 3.0 -- it uses long precision, but you can't really tell:

>>> X = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF
>>> X
5192296858534827628530496329220095
>>> oct(X)
'0o17777777777777777777777777777777777777'
>>> bin(X)
'0b11111111111111111111111111111111111111111111 ...and so on...

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
PDF
Page 135
4th paragraph

This syntax makes sense, given that sets are essentially like valueless dictionaries?because they are unordered, unique, and immutable...

should be:

This syntax makes sense, given that sets are essentially like valueless dictionaries?because they are unordered, unique, and mutable...

Note from the Author or Editor:
This sentences is technically correct as is -- its second part talks
about set items, not sets themselves. Still, it's ambiguous enough
to merit a reqording in future printings.

Please see the following for more deatils on the resoultion:

http://www.rmi.net/~lutz/lp4e-updates.html#clari

Wang Zhen  Oct 18, 2009  Jan 01, 2010
Printed
Page 135
the start of the 2nd paragraph under "Set literals in Python 3.0"

[Oct-28-09] Page 135, set items are immutable (though sets are not)

At the start of the 2nd paragraph under "Set literals in Python 3.0", the book states that "This syntax makes sense, given that sets are essentially like valueless dictionaries--because they are unordered, unique, and immutable, a set?s items behave much like a dictionary?s keys." One reader suggested changing "immutable" to "mutable" here, but that would break the intent. This description is technically correct as is, since its last half is discussing the items in a set rather than a set itself. Still, it's a bit ambiguous as worded.

For clarity, change the second part of this sentence as follows: "This syntax makes sense, given that sets are essentially like valueless dictionaries--because a set's items are unordered, unique, and immutable, the items behave much like a dictionary?s keys."

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 135
paragraph 4, line 2

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[May-1-10] {first reprint} Page 135, paragraph 4, line 2: "because because" (minor typo)

Change the "because because" to "because" here. This was introduced by a patch applied in the first reprint (a sentence rewording). It is not present in earlier printings. (In the added text, there is also a straight quote in "set's" that should probably be curly, like all others.)

Mark Lutz
 
Jul 12, 2010  Aug 01, 2010
Printed
Page 137
1st example

"#Only mutable objects work in a set" should read "#Only immutable objects work in a set".

Note from the Author or Editor:
A genuine typo. Please see the following for more details:

http://www.rmi.net/~lutz/lp4e-updates.html

David Hoatson  Oct 24, 2009  Jan 01, 2010
Printed
Page 137
first code listing on this page

[Oct-28-09] Page 137, sets contain immutables (bad code comment)

In the first code listing on this page, the comment "# Only mutable objects work in a set" should read "# Only immutable objects work in a set". This is implied by both the text immediately preceding this code and the examples shown here, but I transposed "immutable" and "mutable" in the comment. Unlike the clarification for page 135 ahead, this is a genuine typo.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 185
the very end of the second paragraph

[Nov-09-09] Page 185, *args in call forward reference (but noted earlier)

On this page, the syntax '...'.format(*parts) makes use of special call syntax to unpack an iterable's items into separate arguments. This feature isn't covered in full until much later in the book. This isn't a forward reference error, though -- although it's not noted here specifically, this syntax is noted briefly earlier in the book. For forward references like this, the book doesn't necessarily repeat the note at every occurrence.

To clarify further, though, add the following at the very end of the second paragraph on page 185 and just before the colon there: "(note the use of *parts here to unpack a tuple's items into individual arguments, as we did on Page 132 when studying fractions; more on this in Chapter 18)". The "*parts" in this should be fixed-width font.

Specifically, this call syntax is described in conjunction with fraction ratios on page 132, which states: "(the * in the second test is special syntax that expands a tuple into individual arguments; more on this when we study function argument passing in Chapter 18)". A **dict forward reference is also noted on page 189, which states: "(as we?ll see in Chapter 18, the **data in the method call here is special syntax that unpacks a dictionary of keys and values...)". Like many things in this book, full coverage is deferred until later in the book; more on this on the book's updatespage listed below.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 186
the very end of the 3rd-last paragraph

[Nov-09-09] Page 186, dict() forward reference (to refer back to page 91 insert)

This is related to the clarification for page 91 earlier on this page. On page 186, at the very end of the 3rd-last paragraph that ends with "10-character-wide field", add this text just before the colon there: "(note the use of dict() to make a dictionary from keyword arguments, introduced in Chapter 4 and covered in Chapter 8)". The "dict()" in this should be fixed-width font.

It's impossible to add forward notes for every deferred topic like this, but this case seems especially glaring to me.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 195
the very first line on page

[Nov-10-09] Page 195, bytearray is mutable too (type summary is informal)

I resisted including both 3.X's bytes and bytearay types and 2.6's unicode type in the datatype lists in this section on purpose, to avoid getting too fine grained or version specific at this point in the book. bytes, bytearray, and 2.6 unicode are kinds of strings; are introduced earlier in this chapter but mostly deferred till Chapter 36; and are included in the later type summaries and figures in Chapter 9 (see pages 240 and 249).

Since bytearray is available in both 2.6 and 3.X, though, we'll clarify this a bit here: at the very first line on page 195, change "Mutables (lists, dictionaries, sets)" to "Mutables (lists, dictionaries, sets, bytearray)".

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 201
Immediately after the "Indexing, Slicing, and Matrixes" header

[Nov-10-09] Page 201, Need a space in "Becauselists" (dropped by production in QC2)

Immediately after the "Indexing, Slicing, and Matrixes" header on this page, change "Becauselists" to "Because lists". Oddly, the space was there in the material I sent, and remained in both the copyedit and QC1 quality-control drafts; it was dropped in the QC2 version, long after anyone had time to catch it. Must have been either careless fingers or a formatting tool bug...

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 216
first code listing of the sidebar on this page

Nov-08-09] Page 216, "anydbm" renamed "dbm" in 3.X (lingering reference)

In the first code listing of the sidebar on this page, change the two "anydbm" to "dbm". Also change the one "anybdm" in the paragraph following this to "dbm (named anydbm in Python 2.X)"; omit word "named" if it does not fit, and make both "dbm" and "anydbm" literal font.

This isn't necessarily a bug since the book covers both Python lines; the rest of the book is 3.X with 2.X exceptions noted, though, and we should be the same here. The new "dbm" name is noted on page 670, which is listed under "anydbm" in the index, but this still deserves a fix here.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 216
first sidebar code listing, line 2, comment

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[May-1-10] {first reprint} Page 216, first sidebar code listing, line 2: "#" misaligned (cosmetic only)

Not a bug and purely cosmetic, but the "# Link to file" comment should be moved 3 spaces to the right so it aligns vertically with the other "#" comments below it. This was introduced by a patch applied in the first reprint (the "anydbm" to "dbm" change). It is not present in earlier printings.

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed
Page 217
N/A

[Nov-08-09] Page 217, keywords appear in other places too (links, dependencies)

[No fix required: clarification only]

When presenting the dict(name=value) form on this page, it's mentioned that keyword arguments were encountered earlier at list.sort(). True, but they also appear at str.format() on page 184 and beyond, where it is noted that they are covered in full in Chapter 18, as well as in print() calls on pages 164 and 200, where they are not explained at all.

I'm not going to patch this page because page 184 links to the full coverage, and this is a general forward dependency issue that is further described at the page 91 clarification above and in the general book notes on the page listed below--in a linear book like this, such dependencies have to be deferred or presented in piecemeal fashion. Again, you can always look up the fine points of dict(), print(), and others in references; watch for the in-depth coverage of keyword arguments in Chapter 18; or jump to this coverage early--much of it is accessible through this book's Index and Table of Contents.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009 
Printed, PDF,
Page 233
start of the second code listing

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 233, second code listing: filename is missing its ".txt" extension

At the start of the second code listing on this page, change "for line in open('myfile'):" to "for line in open('myfile.txt'):", adding just the ".txt" at the end of the file's name. No idea how the extension was dropped here (or added elsewhere?). Also, if and only if there is space at the very end of the immediately preceding line, add the text "(shown here with a Python 3.X print call)"; minor, but a reader found this confusing when it failed on Python 2.6.

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed
Page 234
last two examples in the first code listing section of page

[Nov-10-09] Page 234, line dropped in partial binary data file example

The last two examples in the first code listing section of page 234 aren't completely correct as shown; their "data[0]" is integer zero, not the first character of 'spam' as intended. I can't reconstruct the cause, but given that this code did work as shown, an additional line "data = data[4:8]" was apparently dropped in a cut-and paste somewhere.

To fix, change both occurrences of "data[0]" near the end of this listing to "data[4:8][0]". That is, this listing should look like this (with the rest of the # code comments which I truncated for this posting only):

>>> data = open('data.bin', 'rb').read() # Open binary file:...
>>> data # bytes string holds...
b'\x00\x00\x00\x07spam\x00\x08'
>>> data[4:8] # Act like strings
b'spam'
>>> data[4:8][0] # But really are small...
115
>>> bin(data[4:8][0]) # Python 3.0 bin()...
'0b1110011'

Most readers probably won't notice this error, because the example is deliberately incomplete anyhow, and isn't intended to work as shown -- like its excerpt on page 98, (noted in the clarifications list ahead), it assumes the existence of a binary file which isn't created until later in this chapter (on page 237). Still, this example's treatment of binary data is partly incorrect as is. Ironically, this code was adapted from a more complete example in Chapter 36, on pages 931-932, which is coded correctly; see Chapter 36 for more on binary files and data.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 238
3rd line of page

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 238, 3rd line of page: struct.unpack output shows 2.6 str instead of 3.X bytes

The code listing in line 3 from page top which reads "(7, 'spam', 8)" should read "(7, b'spam', 8)" with the leading "b" on the string in the middle to reflect Python 3.X behavior, as is shown correctly on page 931 where this example is repeated with further elaboration. Again, the book covers 2.X too, but this is ambiguous as shown. Apparently another case of code run under 2.6 inadvertently (or at least without saying so).

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed
Page 295
middle of 1st sentence in notebox

[Aug-1-10] Page 295, middle of 1st sentence in notebox: wording broken by production in QC1

A year after publication, I still find instances of meaning having been broken badly by edits made after I submitted the final draft to production. Here's the latest: the start of this sentence was reworded to make it refer to a prior section in the book, when it was obviously meant to refer to a section of an external web page. The rewording makes no sense at all, even on shallow reading.

To fix, change:
"For additional naming suggestions, see the previous section ?Naming conventions? of Python?s semi-official style guide, known as PEP 8."

to use the original wording as follows:

"For additional naming suggestions, see the discussion of naming
conventions in Python?s semi-official style guide, known as PEP 8."

Also remove the link in this for text "Naming Conventions"; this is about a web page, not about the section of the same name elsewhere in this chapter! As far as I can reconstruct, this error was introduced after copyedit, and first appeared in QC1--far too late to be caught.

[cross-posted from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Aug 01, 2010  Jan 01, 2011
Printed, PDF,
Page 301
Table 11-5, row 3 column 3

[Sep-27-10] Page 301, Table 11-5, row 3 column 3: minor inconsistency in 2.6 print table

In this row/column, change "myfile.write" to "afile.write", to match the other columns in this row. Not an error since the table is abstract anyhow (and no readers have reported this as confusing), but worth a patch for consistency.

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  Jan 01, 2011
Printed, PDF, ePub, Mobi,
Page 304
End of paragraph 3 under "The Python "hello world" program"

[Also posted for 5th Ed] Not an error, but for clarity, expand this sentence:
"""
In fact, if you enjoy working harder than you must, you can also code print operations this way:
"""
To the following, adding only the parenthesized text just before the colon, with links to the two referenced chapters (and please let me know if this changes page breaks; I'm hoping to avoid that):
"""
In fact, if you enjoy working harder than you must, you can also code print operations this way (per Chapters 4 and 9, a 3.X-only return value is omitted here):
"""

[Discussion only follows] A reader wrote by email:
>
> This is on page 357 of the Ebook; page numbering doesn't seem
> to match the print edition. Looking at the last example before the
> "Manual stream redirection" subheading in chapter 11:
>
> >>> import sys
> >>> sys.stdout.write('hello world\n')
> hello world
>
> The system call of course returns a result, and when run
> interactively the result is also printed. As such, when running this
> example under Linux an additional line is added:
>
> >>> import sys
> >>> sys.stdout.write('hello world\n')
> hello world
> 12
>
> where the "hello world" is the text written and the "12" is the result
> of the sys.stdout.write() call. I couldn't find any mention of this on
> your or O'Reilly's errata pages. The omission could be deliberate,
> but some people would find the extra line confusing. I would
> expect the Windows version would add a similar line. There is
> also no mention of this in the following text (i.e. that print always
> returns None where write() returns the number of characters
> written).

Sure, but this isn't platform specific, and is probably not an issue for most readers. The return value of the file's write method is well documented in general file coverage earlier in the book -- starting on Page 122, and spanning Chapters 4 and 9, including the blanket note on Page 288 that reads this way:

"... (for space, I'm omitting byte-count return values from write methods from here on):".

Still, this seems a potential point of confusion, especially for non-linear readers using 3.X. To clarify, I'm suggesting the addition of another parenthetical note about the deliberate omission of the return value in this section, as described above. Such reminders risk becoming overly redundant, but this one seems justified.

Mark Lutz
 
Oct 07, 2013 
Printed, PDF,
Page 305
end of 2nd code listing, comment

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 305, end of 2nd code listing: minor typo in comment, "Bad" should be "Bad!"

Trivial, but inaccurate as is; change the text of just the code comment on the right from "# 2.6: print >> sys.stderr, 'Bad' * 8" to "# 2.6: print >> sys.stderr, 'Bad!' * 8", adding just the "!".

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed, PDF,
Page 332
4th paragraph

It says, "A pass is also sometime coded to mean "to be filled in later,"...

'sometime' should be 'sometimes'.

Note from the Author or Editor:
Yes -- please fix as described.

AJ  Jun 06, 2012  Oct 12, 2012
Printed, PDF
Page 335
code snippets

(A reader wrote to ask how code snippets on page 333 could
be made to actually run; my reply/clarification is below.
If we have space to patch in reprints, add the text "(this
code is intentionally abstract and incomplete: x is a sequence
and match() is a tester function to be defined)" just before
the first code listing on this page)

Thanks for your note. You have a valid point: this code snippet
is intended to be abstract and partial, but it's not explicitly
described as such. In fact, the prior page's primes code is
similarly abstract, though this fact is better noted there.

To make it work as real, live code, "x" would have to be a sequence
such as a list or string, and "match()" would have to be a function
which checks for a match against an object passed in. As a
completely artificial example:

x = list(range(100))
def match(I):
return I > 50

A better example might make x a list of dictionary "records",
and match() a test against a dictionary key's "field" value
(e.g., looking for a record with a name value known to match()).

The abstract code snippet in the book strips off successive items
at the front of "x" and passes each into this function in turn.
I couldn't show a function like match() at this point in the
book, though, without yet another forward dependency (functions
are not covered until the next part). The goal here was to illustrate the loop else by itself.

I also chose not to elaborate here because in practice a "for" loop
is probably better than a "while" for this code, and iteration
tools such as filter() and list comps might be better than both:

x = [....]
for item in x:
if match(item):
print('Ni')
break
else:
print('Not found')

x = [....]
print('Ni' if [item for item in x if match(item)] else 'Not found')

x = [....]
print('Ni' if filter(match, x) else 'Not found')

Try running these alternatives on your own to see what I mean.

Mark Lutz
 
Aug 31, 2010  May 20, 2011
Printed, PDF,
Page 348
bottom line of the second paragraph

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 348, bottom line of the second paragraph: minor typo, "cal" to "call"

Change "to the dict cal for" to read "to the dict call for".

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
Printed, PDF,
Page 348
2nd last line of the second paragraph

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-12-10] Page 348, 2nd last line of the second paragraph: minor typo, need a comma

Same sentence as prior item: Change "dictionary comprehensions an alternative" to read "dictionary comprehensions, an alternative" by adding the comma. This reflects a change made in copyedit; the comma was present in the original and this seems to read better if present.

Mark Lutz
 
Jul 12, 2010  Jan 01, 2011
, Printed, PDF, , Other Digital Version
Page 356 and 357
Last section of Code

>>> L = [1, 2, 3]
>>> I = iter(L) # Obtain an iterator object
>>> I.next() # Call next to advance to next item
1
>>> I.next()
2
...

Switching from __next__() to next() methods without explicit reference to version differences.

Note from the Author or Editor:
Yes indeed -- I'm surprised this wasn't caught before this, but it does merit a fix in reprints. Here is the full post at my errata page, with correction instructions:
----

[Feb-5-11] Page 354-355, code listing that spans pages: use 3.X I.__next__(), not 2.X I.next()

A reader noticed that this code listing uses Python 2.X style next() iteration methods, but does not state so explicitly. I'd like to simply add a note to this effect, but in this case that could be confusing, and is probably a cop out: all the other listings in this section use the 3.X style __next__(), and this one should match. This 2.X/3.X difference is stated in note boxes on pages 356, 494, and 712, and mentioned on pages 707 and xxxvi. The 2.X code here is either legacy from the prior edition, or was run in a 2.X window -- yet another artifact of dual-version coverage.

To fix, change ">>> I.next()" to read ">>> I.__next__()", adding the leading and trailing double underscores around "next", in all 4 appearances here: lines -4 and -2 of page 354, and lines 1 and 3 of page 355. Be careful to not alter the fonts or the vertical alignment of the "#..." comments to the right in the process. When applied, the full interaction that spans these two pages should look like this:

>>> L = [1, 2, 3]
>>> I = iter(L) # Obtain an iterator object
>>> I.__next__() # Call next to advance to next item
1
>>> I.__next__()
2
>>> I.__next__()
3
>>> I.__next__()
Traceback (most recent call last):
...more omitted...
StopIteration

Anonymous  Jan 09, 2011  May 20, 2011
Printed, PDF, , Other Digital Version
Page 371
code example following the 3rd paragraph

>>> D
{'a': 1, 'c':3, 'b':2}
>>> for k in sorted(D.keys())): print(k, D[k], end=' ')
...
a 1 b 2 c 3

---

list() call missing, closing parenthesis mistakenly remaining
should probably read:

>>> D
{'a': 1, 'c':3, 'b':2}
>>> for k in sorted(list(D.keys())): print(k, D[k], end=' ')
...
a 1 b 2 c 3

Note from the Author or Editor:
Yes -- there is one extra ")" in this which should be deleted in reprints.

Change:
>>> for k in sorted(D.keys())): print(k, D[k], end=' ')

to read:
>>> for k in sorted(D.keys()): print(k, D[k], end=' ')

While the extra character was a genuine typo here, this user case was also presented correctly on Page 222. Moreover, there is no need to insert a list() call here as suggested by the poster (though this may indeed be the origin of the extra right paren); a list() call here would add pointless extra work, because sorted() accepts any iterable, including a dictionary view.

Anonymous  Feb 13, 2011  May 20, 2011
Printed
Page 413
add a new footnote at the bottom of page 413

[Nov-01-09] Page 413, Chapter 17, scopes and loop variables in comprehensions (add new footnote)

To clarify, in future printings of the book we'll add the following text as a footnote at the bottom of page 413, with its star at the very end of the sentence just before the note box on that page [reprints: please ask me how to shorten this if it does not fit on that page as is]: """There is technically one more scope in Python: loop variables in comprehension and generator expressions are local to the expression itself in 3.X (in 2.X, they are local in generators but not in list comprehensions). This is a special and obscure case that rarely impacts real code, and differs from for-loop statements which never localize their variables.""".

[Discussion follows -- no further reprint changes required]

I wish to clarify an arguably obscure scope issue not covered in the book -- that of loop variables in comprehensions. In 2.X, such loop variables are local to generator expression, but not list comprehensions. In 3.X, they are always local to both kids of expressions, as well as 3.X's new set and dictionary comprehensions. This differs from variables in loop statements which are never local to the statement itself. It also seems almost too academic and arcane to mention (and frankly, it's difficult to imagine a valid use case that would depend upon either behavior), but this is technically another 3.X change that could break 2.X code.

Here's how this pans out in practice -- in 3.X comprehensions localize loop variables, but statements don't:

# Python 3.0

>>> L = [x for x in 'spam']
>>> L
['s', 'p', 'a', 'm']
>>> x
NameError: name 'x' is not defined
>>>
>>> G = (y for y in 'spam')
>>> G
<generator object at 0x02501D00>
>>> y
NameError: name 'y' is not defined
>>>
>>> {x for x in 'spam'}
{'a', 'p', 's', 'm'}
>>> x
NameError: name 'x' is not defined
>>>
>>> {x: x*2 for x in 'spam'}
{'a': 'aa', 'p': 'pp', 's': 'ss', 'm': 'mm'}
>>> x
NameError: name 'x' is not defined
>>>
>>> for z in 'spam': print(z, end=' ')
...
s p a m >>> z
'm'

In Python 2.6, list comprehensions and generator expressions are supported, but the former does not localize its loop variables -- they retain their last iteration value, just like for-loop statements:

# Python 2.6

>>> L = [x for x in 'spam']
>>> x <=== DIFFERS
'm'
>>>
>>> G = (y for y in 'spam')
>>> y
NameError: name 'y' is not defined
>>>
>>> for z in 'spam': print z,
...
s p a m
>>> z
'm'

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 425
Near the end of paragraph 4 on this page

[Oct-28-09] Page 425, changeable state information, not scope information

Near the end of paragraph 4 on this page, "changeable scope information" should read "changeable state information". While not technically wrong as is (since this section deals with saving information in an enclosing scope), this was really intended to mention state information, as implied by that term's many other appearances in this section.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 429
the last sentence of the 4th paragraph on this page

[Nov-06-09] Page 429, next "three" sections, not "two" (minor typo)

In the last sentence of the 4th paragraph on this page, "next two sections" should read "next three sections". The third section, on function attributes, was added as something of an afterthought, and this sentence wasn't updated. See also the page 431 clarification later on this webpage; the added third section seems like it could use a bit of elaboration in general.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 431
add a new footnote on page 432 and a new index entry

[Nov-06-09] Page 431, alternative scope-based state retention technique (add new footnote)

To clarify this in future printings, make two changes:

1) Add a footnote star at the very end of the first paragraph on page 432, referencing a new footnote on page 432 that has the following text: """Function attributes are supported in both Python 2.6 and 3.X. We'll explore them further in Chapter 19, and revisit all the state options introduced here in Chapter 38 in a more realistic context. Also note that it's possible to change a mutable object in the enclosing scope in 2.X and 3.X without declaring its name nonlocal (e.g, state=[start] in tester, state[0]+=1 in nested), though it's perhaps more obscure than either function attributes or 3.X's nonlocal.""". Within this new footnote text, "state=[start]", "tester", "state[0]+=1", and "nested" should all be in fixed-width font.

2) Add page 471 to the index entry for "function attributes" (though it's already mentioned in function/attributes and annotations).

[Reprints: please let me know if these two changes need clarification or trimming.]

[Discussion follows -- no further reprint changes required]

I want to point out an alternative to a book scopes example. The last section on page 431 gives an example of using function attributes to retain per-call state information, as an alternative to the 3.X-only "nonlocal" statement. The following example from the book (which runs in both 2.X and 3.X) works because each call to the outer function runs a nested def to make a new function object; it also allows the state information to be accessed from outside the function if needed:

# Python 2.X and 3.X: function attributes (in book)

>>> def tester(start):
... def nested(label):
... print(label, nested.state)
... nested.state += 1 # changes object, not name
... nested.state = start # per-call state is retained:
... return nested # each tester() makes new func
...
>>> F = tester(0)
>>> F('spam')
spam 0
>>> F('eggs')
eggs 1
>>>
>>> G = tester(42) # each nested func object has its own state
>>> G('ham')
ham 42
>>> G('bacon')
bacon 43
>>>
>>> F('sausage')
sausage 2
>>> F.state, G.state # and state is accessible from outside
(3, 44)

Interestingly, you can achieve the same effect with a reference to a mutable object in the enclosing scope instead of an attribute attached to the function itself, albeit at some arguable cost in code simplicity. The following alternative, not listed in the book, works similarly because each call to the outer function gets a new local scope; unlike function attributes, though, the state is not directly visible outside the function:

# Python 2.X and 3.X: change mutable in enclosing scope (not in book)

>>> def tester(start):
... def nested(label):
... print(label, state[0])
... state[0] += 1 # changes object, not name
... state = [start]
... return nested
...
>>> F = tester(0) # per-call state retained again:
>>> F('spam') # each tester() has new local scope
('spam', 0)
>>> F('eggs') # but no F.state accessible here
('eggs', 1)
>>>
>>> G = tester(42)
>>> G('ham')
('ham', 42)
>>> G('bacon')
('bacon', 43)
>>>
>>> F('sausage')
('sausage', 2)

Of course, as shown in the book, the 3.X "nonlocal" statement offers an alternative that is often seen as more straightforward than both the above schemes; its only potential downside is that unlike function attributes, the state it retains is not directly visible outside the function (which may matter in some contexts):

# Python 3.X only: nonlocal statement (in book)

>>> def tester(start):
... state = start
... def nested(label):
... nonlocal state # change enclosing scope name
... print(label, state) # but state not visible outside
... state += 1
... return nested
...
>>> F = tester(0)
>>> F('spam')
spam 0
>>> G = tester(42)
>>> G('eggs')
eggs 42
>>> F('eggs')
eggs 1
>>> F.state
AttributeError: 'function' object has no attribute 'state'

Also see the further coverage of function attributes in page 471; this probably should be noted at the earlier page 431 example, along with the fact that both 2.6 and 3.X support function attributes, and the rehash of these techniques in the decorators chapter. To clarify all this a bit in future printings, make the two changes described above.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF, ePub, Mobi,
Page 438
Paragraph 2 in section "Arguments and Shared References"

[No change required: reposting as informational author note only.]
A reader posted:

> Page: 438
> Location: 7th paragraph in page
> Description:
> "In this example the variable a is assigned with the object 88 at the
> moment the function is called with f(b), but a lives only within the
> called function."
>
> this should read...
> "In this example the variable a is assigned with the object 99 at the
> moment the function is called with f(a), but a lives only within the
> called function."
>
> changes:
> object 88 --> object 99
> f(b) --> f(a)

No, this wording is correct as is. The suggested change misses the whole point of this section, but seems a confusion common enough to warrant a clarification here.

This section describes the assignment of object 88 -- the value referenced by global variable b -- to variable a, which is a local variable within function f. This assignment occurs automatically when the function f is initially called.

That is, a is assigned 88 at the moment of function call, by virtue of the argument passing mechanism, as stated in the book. Names a and b share the same object at this point. The later assignment of name a to object 99 -- via the code a=99 within f -- simply resets local name a to a different object, and hence does not impact name b outside the function. That's the whole point of this example: the names a and b are not linked in any way.

That said, this text is describing a mechanism that has been historically confusing to some Python newcomers. When studying code like this, remember to keep the fundamental distinction of names and objects clear, and don't let prior language exposure cloud your judgement; Python is everywhere about names, objects, and references.

Mark Lutz
 
Oct 02, 2013 
Printed, PDF, , Other Digital Version
Page 448
line 4 from top

"f(1, *(2,), c=3, **{'d':4})" should be "func(1, *(2,), c=3, **{'d':4})"

Note from the Author or Editor:
Yes, and good catch -- change as described, replacing the "f" at the front of this code line with "func". In the May 2011 reprint this is now at the 4th line of the code section at the top of page 450.

Interestingly, the call show does work with the previous "f" definition, but the output is different, and this wasn't really the intent of this:

>>> def f(a, *pargs, **kargs): print(a, pargs, kargs)
...
>>> def func(a, b, c, d): print(a, b, c, d)
...
>>> func(1, *(2,), c=3, **{'d':4})
1 2 3 4
>>> f(1, *(2,), c=3, **{'d':4})
1 (2,) {'c': 3, 'd': 4}

Marta Recasens  May 31, 2011  Nov 04, 2011
Printed
Page 455
First sentence in "Bonus Points"

You can get can get bonus...

Note from the Author or Editor:
Yes -- this typo went uncaught in review/copyedit.

Armin Galliker  Jan 19, 2010  Jan 01, 2011
Printed, PDF, , Other Digital Version
Page 464
The answer to question 4

The text reads: "4. This time the code prints '1, {'c': 3, 'b': 2}'," I don't believe there should be a comma following "1" The default separator is a space.

Note from the Author or Editor:
Yes -- the first comma here (in "1, ") should not be present; please delete just the single comma character in reprints.

Anonymous  Apr 16, 2011  May 20, 2011
Printed
Page 477
2nd paragraph in How (Not) to Obfuscate Your Python Code

You need not use sys.stdout.write to print from a lambda in Python 3 because print is now an expression instead of a statement.

Note from the Author or Editor:
Yes, this is a genuine issue worth patching in the next reprint (made all the more frustrating by the fact that I've used print() in lambda's often in the Programming Python 4E rewrite just completed). Not an error per se, as the technique shown works in both 2.X and 3.X and the book covers both (it'a a more portable option), but it may be misleading and is 2.X biased.

The following is the description of this issue just posted to the book's errata page I maintain at http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html.

------------

[Jul-8-10] Page 477, paragraph 4: 3.X can use print() instead of sys.stdout.write() in lambda

While not incorrect, the discussion of printing from within a lambda's expression here, and its application in later examples, is a bit 2.X-biased. It suggests using sys.stdout.write(), which is required in Python 2.X because printing is a statement that cannot appear as an expression. In Python 3.X, though, we can simply use a print() call inside a lambda (and drop the explicit "\n" characters), since printing becomes a function-call expression. On the other hand, the sys.stdout.write form works in both Python lines, and so is more portable. Hence this may be more clarification than correction.

To avoid confusion, though, reword the current start of this paragraph: "For example, if you want to print from the body of a lambda function, simply say sys.stdout.write(str(x)+'\n'), instead of print(x) (recall from Chapter 11 that this is what print really does)."

to read as follows, with the "print(x)" and "sys.stdout.write(...)" parts in literal font: "For example, if you want to print from the body of a lambda function, simply say print(X) in Python 3.X (where this becomes a call expression instead of a statement), but say sys.stdout.write(str(x)+'\n') in either Python 2.X or 3.X to make sure it's an expression portably (recall from Chapter 11 that this is what print really does)."

Steve Chapel  Jul 08, 2010  Jan 01, 2011
Printed
Page 483
Quiz question 2

lambda is misspelled lamba

Note from the Author or Editor:
Yes - a genuine typo. Please fix in reprints as suggested.

Steve Chapel  Jul 08, 2010  Jan 01, 2011
Printed
Page 500
last paragraph before Emulating zip and map with Iteration Tools

I think "...it's up to us to decide how any iterations we wish to support..." should be "...it's up to us to decide how many iterations we wish to support..."

Note from the Author or Editor:
Yes--a typo (and I wish this reader had been part of the edit and production process). New entry just posted on my errata page below.

----------------

Jul-8-10] Page 500, middle of 3rd paragraph: minor typo, "how any" should be "how many"

Just before the header that starts "Emulating zip...", change "decide how any iterations" to "decide how many iterations". Present in the original draft, and unnoticed during editing.

Steve Chapel  Jul 08, 2010  Jan 01, 2011
Printed
Page 511
bottom of page (new footnote)

[Dec-15-09] Page 511, note decorator-based timer alternatives in ch38 and ch39 (add new footnote)

In Chapter 20, the book explores general timing functions whih require special call patterns for the functions timed. Later in the book, decorator-based timer alternatives are developed which don't require special call syntax, and it would be nice to have a forward link to the alternative coding here.

Add the following quoted text as new footnote on page 511, with its asterisk at the very end of the paragraph just before heading "Timing Results" [reprints: it looks like we have space, but please ask how to shorten if not]:
"""
Also note how we must pass functions in to the timer manually here. In Chapters 38 and 39 we'll see decorator-based timer alternatives with which timed functions are called normally.
"""

--------
crossposted from http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 15, 2009  Jan 01, 2010
Printed
Page 511
last paragraph before Timing Results

"a tuple of four function objects" should be "a tuple of five function objects"

Note from the Author or Editor:
Yes - a genuine typo. Below is the entry just posted for this on my own errata page, http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html.

-------------
[Jul-9-10] Page 511, paragraph 2 line 5: minor typo, "tuple of four" should be "tuple of five"

A test function was added to the code but the narrative wasn't updated. Change "a tuple of four function objects" to "a tuple of five function objects". Present in the original draft, and unnoticed during editing and tech review.

Steve Chapel  Jul 08, 2010  Jan 01, 2011
Printed
Page 515
paragraph 1, line 2

[Dec-15-09] Page 515, paragraph 1, line 2, extraneous "to" (minor typo)

There's a minor typo here that survived our best intentions: change "both to the total-of-N" to "both the total-of-N".

--------
crossposted from http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 15, 2009  Jan 01, 2010
Printed
Page 518
the second line of code on this page

[Nov-01-09] Page 518, indentation of snippet changed by production

Not a bug unless taken too literally, but on page 518, the second line of code, "print('<{0}>'.format(tester.__name__)) # To method call", was not supposed to be indented four spaces (and was not in the material that I wrote). This is just a line of code snipped out of a larger working script, so it's not an error; still, it looks odd enough to fix -- remove the indentation on this line (only), so it lines up vertically with the first line of code above it.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 518
adding a new footnote on bottom of page

[Dec-14-09] Page 513-518, iteration timings, map() is slow because all function calls are slow (add new footnote)

Add the following text as a new footnote on page 518 (reprints: it looks like we have space on this page but please ask how to shorten if not). Its asterisk should appear at the very end of the last paragraph before heading "Function Gotchas" on page 518, and in this the words "map" and "abs" and the code "def f(I): return(I)" should all be fixed-with font:

""" For more fun, apply a simple user-defined function like def f(I): return(I) in all five iteration techniques timed. The results are similar to using a built-in function like abs: among the five iteration techniques, map is fastest today if all five call a function, built-in or not, but slowest when the others do not. That is, map appears to be slower simply because it requires function calls, and function calls are relatively slow in general. Since map can't avoid calling functions, it can lose by association. """


[Discussion follows -- no further changes required]

This section goes through a code timing example and gives the relative speeds of various iteration alternatives. The map built-in appears to win when a built-in function is applied, and lose to list comprehensions otherwise. All true, but this section wasn't meant as a complete treatise on Python performance, and some additional conclusions were not explored in the interest of space. Among these is a more general further conclusion about map speed which I'd like to note here, and briefly footnote in the book.

Technically, map is relatively slower because it requires function calls, and function calls are expensive in general. It doesn't matter if the function called is built-in or user-defined. To see this for yourself, try changing the timing examples to apply a simple user-defined function; the results are the same as using a built-in function like abs -- map is faster if all five techniques call functions of any variety. Unlike list comprehensions and for loops, though, map can't avoid the cost of function calls, so it is slowed by association. At least that's the case today. As also noted in the book, timing results can vary per release and other variables, so be sure to time code yourself to be sure. Performance measurement is often part black art.

Mark Lutz
 
Dec 14, 2009  Jan 01, 2010
PDF
Page 537
First paragraph under ".pth path file directories". Last sentence.

... we won't them cover fully here, but they ...

should read

... we won't cover them full here, but they ...

Note from the Author or Editor:
A genuine typo. This one was introduced during the copyedit phase,
and reflects a change made to grammatically correct text (I didn't write these words).

Please see the following for more details on the resolution:

http://www.rmi.net/~lutz/lp4e-updates.html

Anonymous  Sep 27, 2009  Jan 01, 2010
Printed
Page 537
the first paragraph under list heading ".pth path file directories"

[Oct-28-09] Page 537, typo in .pth files section introduced by copyedit

In the first paragraph under list heading ".pth path file directories", the text "; we won?t them cover fully here, but" should read "; we won?t cover them fully here, but".

This is the result of a copyedit change to what was a grammatically valid sentence in the final draft. The original read "These path configuration files are a somewhat advanced installation-related feature which we won?t cover fully here, but...".

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
, Printed, PDF, , Other Digital Version
Page 539
paragraph 2, line 5

[Feb-5-11] Page 539, paragraph 2, line 5, minor typo: "mypath.py" should be "mypath.pth"

Per a reader's email, at the start of this line, change the filename extension at the end of the path "C:\Python30\mypath.py" so that it reads "C:\Python30\mypath.pth".

The required ".pth" file extension is described correctly about a dozen times in this section (and again repeatedly in the start-up details appendix), so most readers will probably get past this; but it's worth patching in this one spot where it was munged.

Mark Lutz
 
Feb 05, 2011  May 20, 2011
Printed, PDF,
Page 569
Chapter 23

[Sep-27-10] Chapter 23: The 3.X package-relative import model precludes using directories as both program and package

I posted a clarification about issues related to inter-package imports under the Python 3.X package-relative import model on my main updates page. Since it's too long to paste here, please see the original page for this item, and its suggestion book inserts:

http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html

Mark Lutz
 
Sep 27, 2010 
PDF
Page 586-587

On pg 586 we are dealing with function minmax.py; on 587 we change to function min.py.

Is that correct?

Note from the Author or Editor:
I think the confusion here is really module names: the original module is named "minmax.py" in Chapter 18, but the enhanced version here was renamed "min.py" to avoid a clash. This is implied by the interaction but not stated explicitly.

To clarify, add the following text in parenthesis to the end of the last paragraph on page 590, just after "it is imported" and just before the last code listing on this page, with "min.py" in italics:

"(this new version of the module file is renamed min.py here)"

Anonymous  May 27, 2011  Nov 04, 2011
, Printed, PDF, ePub, Mobi,
Page 618
last-but-one paragraph

"If it?s coded and inherited, Python automatically calls a method named __init__ [...]"

IMO this sentence should be:
"If it?s coded *or* inherited [...]"

Note from the Author or Editor:
Yes: this is a valid typo, now at the start of the second-last paragraph on Page 620,and should be fixed.

Change from:
"If it?s coded and inherited"

To (replacing "and" with "or")
"If it?s coded or inherited"

Aivar Annamaa  Aug 15, 2012  Oct 12, 2012
PDF
Page 638
middle of page

This is for 4th edition.

I have a question/request for clarification for self.name.upper() in the context of the text below:

Even methods, normally created by a def nested in a class, can be created completely independently of any class object. The following, for example, defines a simple function outside of any class that takes one argument:

>>> def upperName(self):
... return self.name.upper() # Still needs a self

There is nothing about a class here yet?it?s a simple function, and it can be called as such at this point, provided we pass in an object with a name attribute (the name self does not make this special in any way):

====

My question:

I am lost about self.name.upper(). Why is this self.name.upper() instead of simply self.upper()?

From the context, 'name' is an attribute of object x and also an attribute of class rec. How can this 'name' attribute have an attribute (the upper() function) of its own? Is it a "nested attribute"? Is there even such a thing in Python?

Maybe I completely misunderstood. Could you please clarify this particular line of code?

Thank you!

Note from the Author or Editor:
Well, the code is correct as shown, but the "self" in it might be a bit confusing (it's just a simple variable name here).

I'd call this nested objects, not nested attributes. To understand it fully, you must evaluate it the way Python does--from left to right, and one expression/operation at a time. Given "self.name.upper()", and adding parenthesis to emphasize the order of operations:

1) (self.name) fetches the value of a "name" attribute from whatever object variable "self" happens to reference.
2) ((self.name).upper) then fetches the value of an "upper" attribute from whatever object was returned by step 1.
3) ((self.name).upper)() finally calls the function object that "upper" is assumed to reference, with no arguments.

The net effect is that "self" references an object, whose "name" attribute references a (string) object, whose "upper" attribute references a (callable) object. It's object nesting; in general, that's what class instance state information always is--nested objects assigned to instance attibutes.

And that why it works to pass "x" to this function directly: "x" is a class instance object, whose "name" attribute references a string object with an "upper"; "x" has no "upper" attribute itself.

Thanks for your note. We don't have space to add text on this page, but hopefully this clarification will help other readers too.

langtechie  Aug 27, 2010 
Printed, PDF,
Page 639
end of 3rd code listing section on page

[Sep-27-10] Page 639, minor output typo at end of 3rd code listing section on page

Change:
>>> print(rec.age)
40

to:
>>> print(rec.age)
45

This looks like an edition skew, given the changed ages listed; probably obvious to most readers, but worth a fix.

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  Jan 01, 2011
Printed, PDF,
Page 649
first sentence on page

[Sep-7-10] Page 649, first sentence on page, "two lines" should probably be "three lines" (minor ambiguity)

Change "We?ve added the last two lines here;" to "We?ve added the last three lines here;". This one is debatable, and was written as it was intentionally: three lines were physically added, but this sentence discusses just the two that actually matter (not counting the simple print at the end). Still, this sounds ambiguous enough as is to seem like a typo to some readers.

Mark Lutz
 
Sep 07, 2010  May 20, 2011
Printed
Page 670
N/A

[Nov-11-09] Page 670, shelve changes and the "writeback" option

[No reprint fix required -- clarification only]

I want to make a minor clarification about shelves. Page 670 states that you must close shelves after making changes, and page 676 states that ZODB writes changes to disk automatically, implying that shelve does not (also implied by a code comment in the update script on page 674). This is all true by default, and no fix is required here -- this book doesn't cover such libraries in any sort of depth.

However, if the shelve.open() call's optional new writeback keyword argument is passed True, all entries accessed are cached in memory, and written back at close time. This makes it easier to change mutable entries in the shelve, but can consume memory for the cache, and can make the close operation slow because all accessed entries are written back. You still must close the file after changes as stated; the only difference is that with this option you need not manually reassign changed objects to their keys in the shelve in order to write changes to disk.

See Python's library manual, reference books, or application-focused books for more details on shelve.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009 
Printed, PDF,
Page 681
4th paragraph (Answer #8)

"Test Your Knowledge: Answers" for Chapter 27:
In the 4th sentence of #8, smptlib should be smtplib

Note from the Author or Editor:
Yes -- please fix typo as described.

Selby  Jun 13, 2012  Oct 12, 2012
Printed, PDF, , Other Digital Version
Page 708
Answer #3

(Reposting this from the 3rd Ed's list, where the original
inadvertently appeared.)
>
> Type: Language change or typo
> Page: 704
> Location: answer 3.
> Description:
> "A class must manually call the __init__ method in a
> superclass if it defines an __init__ constructor of its own"
>
> Am I right in guessing you mean that the subclass constructor does not automatically call its superclass constructor(s)?
>
> I'm guessing many readers would finish the sentence believing that an exception will be thrown if they forget to code
a superconstructor call.
>

No, the second half of this sentence left out of this post, "but it also must still kick off the superclass?s construction code", means you need to make the call only if you need the superclass's constructor code to be run too.

This is also well documented earlier in the Chapter itself -- see especially section "Calling Superclass Constructors" where this is made very clear-- and the exercises are just a review of this material. Still, the language here is a bit loose, and reflects some editing made during production.

To clarify, let's change the first sentence of answer #3 now on Page 708 to read as follows (__init__ is literal font):

"3. A class must manually call the __init__ method in a superclass if it defines an __init__ constructor of its own and still wants the superclass?s construction code to run."

Mark Lutz
 
Oct 29, 2011  Nov 04, 2011
Printed
Page 713
second last paragraph on this page

[Oct-28-09] Page 713, grammar botched in last minute text insert by production

The wording in the second last paragraph on this page was broken by production when applying an insert I requested at the very end of this project. The text "generator functions (topics or expressions introduced" was supposed to read "generator functions or expressions (topics introduced". In production's defense, the generator expression comment added here at the same time went in correctly.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 718
Page 718 and 719, code listings' raise statements

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 718 and 719: two lingering 2.X-style raise statements in code examples

The __getattr___/__setattr__ examples here use Python 2.X raise statements, and were apparently run under 2.6 inadvertently. I'm not sure this qualifies as an error per se, as this book covers both 2.X and 3.X, and the raise difference is spelled out in detail repeatedly in the next part of the book (raising exceptions hasn't really been covered yet in full at this point). Still, this seems potentially confusing enough to merit a change.

To fix, change the two raise statements in the last code listing on page 718 and the first code listing on page 719, from:

raise AttributeError, attrname
raise AttributeError, attr + ' not allowed'

to the following, by deleting the commas and adding parens (keep their indentation exactly the same as it is currently--reprints: please ask me to verify the change if in doubt, as this is program code):

raise AttributeError(attrname)
raise AttributeError(attr + ' not allowed')

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF, , Other Digital Version
Page 728
at empty space at bottom of page

[Jul-29-11] More on right-side operator methods: __radd__ = __add__

At the empty space at the bottom of page 728, after the final code listing on this page, add a new short paragraph that reads as follows with all __radd__ and __add__ in literal font (it looks like there's ample room, but please ask how to shorten of not):

"""
For truly commutative operations which do not require special-casing by position, it is also sometimes sufficient to alias the right-side __radd__ to the left-side __add__, by simply assigning the former name to the latter at the top-level of the class statement. Right appearances will then trigger the single, shared __add__ method passing the right operand to self.
"""

For more details on this clarification with examples, see:
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html#radd

Mark Lutz
 
Jul 29, 2011  Nov 04, 2011
Printed, PDF, , Other Digital Version
Page 728
empty space at very end of page

[Jul-29-11] Page 728: more on right-side operator overloading methods: __radd__ = __add__

At the empty space at the bottom of page 728, after the final code listing on this page, add a new short paragraph that reads as follows with all __radd__ and __add__ in literal font (it looks like there's ample room, but please ask how to shorten if not):

"""
For truly commutative operations which do not require special-casing by position, it is also sometimes sufficient to alias the right-side __radd__ to the left-side __add__, by simply assigning the former name to the latter at the top-level of the class statement. Right appearances will then trigger the single, shared __add__ method passing the right operand to self.
"""

For detailed discussion on this with code examples, please see my updates page note: http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html#radd.

Mark Lutz
 
Oct 29, 2011  Nov 04, 2011
Printed
Page 728
Insert a sentence at the start of the 5th paragraph on page 728

[Nov-11-09] Page 728, Bound methods already defer calls -- avoid superfluous lambdas!

Insert a sentence at the start of the 5th paragraph on page 728, so that it reads: "Note that a lambda is not required here, because a bound method reference by itself already defers a call till later (again, more on bound methods in Chapter 30). This technique is simpler, ...". It look's like there is plenty of space on this page.

[Discussion only follows -- no further reprint changes required]

I'm adding this to underscore a point about deferred code which is already covered by the book but is an apparently common stumbling block. This section, as well as the more complete coverage in Chapter 30 with its sidebar on page 756, show how bound methods, named through self, may be used as callback handlers, because they are callable objects.

For instance, the following registers self.handler as the event handler for a tkinter GUI event. As explained in the book, referencing the method without calling it like this (i.e., without coding parenthesis after it) is sufficient to defer its call until the event later occurs and invokes a call:

>>> from tkinter import *
>>>
>>> class MyGui:
... def __init__(self):
... self.color = 'Blue'
... Button(text='Spam', command=self.handler).pack(side=TOP)
... def handler(self):
... print('Got it:', self.color)
...
>>> X = MyGui()
>>> mainloop() # and press button in GUI
Got it: Blue
Got it: Blue

Recently, though, I've seen the following sort of variation in a variety of Python code on the web -- using a lambda to defer a method call. This shows up even in tutorials for popular Python frameworks. But the lambda in this is completely pointless -- if you simply leave the parenthesis off, self.handler calls are already deferred:

>>> class MyGui:
... def __init__(self):
... self.color = 'Blue'
... Button(text='Spam',
... command=(lambda: self.handler())).pack(side=TOP)
... def handler(self):
... print('Got it:', self.color)
...
>>> X = MyGui()
>>> mainloop()
Got it: Blue
Got it: Blue

Both versions work, but the lambda in the second is superfluous overkill, and probably reflects a lack of knowledge about Python's bound methods (if not bad habits from other programming languages). Lambda is required in other contexts that need more than a deferred method call (e.g., when you must also specify arguments to be passed to the method); here, though, it's just extra code, and incurs the performance penalty of an extra call.

This is exactly the sort of subtle mistake that abbreviated Python introductions often miss, and which in-depth books like Learning Python are designed to address and prevent. See, for instance, pages 727-728, 750-756, and 479. The 3rd Edition of the application-focused book Programming Python naturally covers GUI callback coding options as well (especially on pages 390-399).

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 732
top of page

Change the sentence at the top of this page:

"""
With OOP, the state remembered is made explicit with attribute assignments.
"""

to the following (with "nonlocal" in literal font):

"""
With OOP, the state remembered is made explicit with attribute assignments; this makes its model generally the most Pythonic, though 3.X's nonlocal statement makes enclosing scopes a viable alternative in some roles.
"""

I'm changing this because the text preceding this suggests that classes are best for state retention, but doesn't clearly explain why, and may be a bit too absolute given the growing popularity of enclosing scope state in Python (formally known as closures, and representative of a trend towards functional techniques).

Reprints: It looks like there is space for a line or two at the end of this page; please ask how to shorten if it changes paging.

Mark Lutz
 
Oct 30, 2011  Nov 04, 2011
Printed
Page 746
the third-last line of the last code listing on this page

Nov-11-09] Page 746, use list() around dict.keys() in 3.X (a missed occurrence)

In the third-last line of the last code listing on this page, change ">>> x.keys()" to ">>> list(x.keys())".

Without the list(), the output of this line shown is produced in Python 2.X, not 3.X. I'm not marking this as an error since the need to wrap key lists in list() for 3.X only is documented in numerous places before this; using list() is superfluous for 2.X readers; and this book covers both 3.X and 2.X. Moreover, the rehash of this example later on page 1013 does use the list() call. Still, list() is used for key lists everywhere else to emphasize 3.X usage, so this occurrence might confuse if not changed.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 748
line 4 of "Why you will care" sidebar

(Reposting this from the 3rd Ed's list, where the original
inadvertently appeared.)
>
> Type: Serious technical mistake
> Page: 744
> Location: line 4 of "Why you will care"...
> Description:
> "picking" should be "pickling".
>

Yes -- change "by picking or shelving" to "by pickling or shelving", at the end of line 4 of the sidebar that is now on Page 748 in the May 2011 reprint.

(Type changed: this is hardly a serious technical mistake!)

Mark Lutz
 
Oct 29, 2011  Nov 04, 2011
Printed, PDF,
Page 755
line -8 on page, comment in last code listing

[Sep-27-10] Page 755, line -8 on page, comment in last code listing: dict comps not in 2.6

Change "# 2.6/3.0 dict comprehension" to "# 3.0 dict comprehension". An unreported minor typo in a code comment only, but worth a fix in reprints. As explained elsewhere repeatedly, the dict comprehension expression is a 3.X addition to the language, not present in 2.6 (though it was also picked up by 2.7 after book published).

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  May 20, 2011
Printed, PDF, ePub, Mobi,
Page 758
In sidebar "Why You Will Care: Bound Methods and Callbacks", last paragraph and code sample

The last code sample defines a class named 'MyWidget', with a method named 'handler'. The first sentence in the following paragraph refers to "MyGui.handler". "MyGui" should be changed to match the class name in the code snippet, i.e. "MyWidget".

Note from the Author or Editor:
Yes--patch as described in the 4th Edition.

[In the 5th Edition, this is repaired such that the name of the class becomes "MyGui", to match the later reference in the narrative.]

Anonymous  Oct 12, 2012 
Printed
Page 758
last line of the last code listing on this page

[Nov-11-09] Page 758, "retubrn" should be "return" (minor typo)

The last line of the last code listing on this page should read "return result", not "retubrn result", of course. This code was tested extensively, so I have no idea where this came from; it's in an early draft, so it may have been happy fingers on my part (that, or sleeping at the keyboard...).

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
, Printed, PDF, , Other Digital Version
Page 767, 786
see description text

[Nov-22-10] Pages 767, 786: more on new-style inheritance method resolution order (MRO)

First, on page 767, at the end of the very last paragraph before the note box on this page, add the following new sentence ("class.mro()" in both of the text inserts should be literal font): " For more ideas, see also Python manuals for the class.mro() new-style class object method, which returns a list giving the class tree search order used by inheritance; this could be used by a class lister to show attribute sources. ".

Second, at the very end of the last paragrph on page 786, add a new sentence which reads: " To trace how new-stye inheritance works by default, see also the class.mro() method mentioned in the preceding chapter's class lister examples. ".

----
[For a full discussion of this topic, please see my main errata page from which this change was copied:
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html]

Mark Lutz
 
Nov 22, 2010  May 20, 2011
Printed, PDF, , Other Digital Version
Page 768
second paragraph "This version also takes care..."

This section briefly hints at commenting out the lines that implement check and skip of the __X__ attributes. I've tried this on both the downloaded example code, and code that I manually typed out.

When implemented the code change essentially comments out a few lines in the for loop of the ListTree.__attrnames method:

...
for attr in sorted(obj.__dict__):
## if attr.startswith('__') and attr.endswith('__'):
## result += spaces + '{0}=<>\n'.format(attr)
## else:
result += spaces + '{0}={1}\n'.format(attr, getattr(obj, attr))
...
(result generation has been unindented for removed if loop)

When I re-run testmixin.py, I get this series of errors:
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "C:\Users\ewbrown\Dropbox\Learning Python\testmixin.py", line 18, in <module>
print(X)
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 58, in __str__
self.__listclass(self.__class__, 4))
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 75, in __listclass
''.join(genabove),
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 69, in <genexpr>
genabove = (self.__listclass(c, indent+4) for c in aClass.__bases__)
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 75, in __listclass
''.join(genabove),
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 69, in <genexpr>
genabove = (self.__listclass(c, indent+4) for c in aClass.__bases__)
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 74, in __listclass
self.__attrnames(aClass,indent),
File "C:\Users\ewbrown\Dropbox\Learning Python\lister.py", line 85, in __attrnames
result += spaces + '{0}={1}\n'.format(attr, getattr(obj, attr))
TypeError: Type method_descriptor doesn't define __format__
>>>

However, if I replace the format method call with this equivalent format expression(below), the error goes away.

result += spaces + '%s=%s\n' % (attr, getattr(obj, attr))

Can you comment on this?

Thanks,
-ewb

Note from the Author or Editor:
This reflects another change (and probably a bug) in Python 3.2.
It's not a problem with the book's examples, though it probably
merits a note here with other 3.2 impacts on the book.

The book's code here works as shown and described in Pythons
2.6, 2.7, 3.0, and 3.1, the versions it applies to. In Python 3.2
only, some objects apparently fail to inherit a default __format__
method, present in the top-level "object". This causes such objects
to fail in the str.format() method, even though, as the poster
discovered, they still work in the "%" formatting expression in 3.2.

To fix: use the "%" expression in this example; use Python 3.1;
or post this to the python-dev bug list at python.org if it's
not yet reported and watch for a patch (try searching the PEPs
there; the exact cause or rationale for this Python regression
may be more subtle than implied here).

For more details, see the longer writeup at:
http://www.rmi.net/~lutz/lp4e-updates-notes-recent.html#py32formatbug

Eric Brown  Jan 20, 2012 
Printed
Page 777
the second bullet on this page

[Oct-28-09] Page 777, 2.6 classes must derive from object _explicitly_

In the second bullet on this page, I'd like to underscore that the derivation from "object" in Python 2.6 new-style classes must be explicit. Change "In Python 2.6 and earlier, classes must inherit from object" to "In Python 2.6 and earlier, classes must explicitly inherit from object".

This is implied by the following code example, but the "explicit" should be made (well...) explicit, since the preceding bullet does so.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 778
5th line from page bottom

Change:
"and all classes (and hence types) inherit from object."

by adding text at the end to read:
"and all classes (and hence types) inherit from object, which comes with a small set of default operator overloading methods."

This is described ahead on Page 787 and in the context of other examples, but it seems important enough to mention in this summary (and it looks like there is ample space on this page). The default methods of object in new-style classes such as __str__ can sometimes be problematic if not anticipated.

Mark Lutz
 
May 17, 2011  May 20, 2011
PDF
Page 790
First sentence

The clause "since dir also returns inherited..." seems like a non sequitur. My distillation of "Instance slots" was: In 2.6 __slots__ would be a meaningless instance attribute (that happens to be a list), but in 3.0 it will suddenly take on meaning and preclude arbitrary attribute names, but you can always bypass that preclusion by putting __dict__ in __slots__, and then you should be careful to use getattr to abstract out all the twists.

Note from the Author or Editor:
(This is now the first non-code paragraph on page 794.) The point here is the dir() also includes inherited attrs, and code that wants just the instance's attrs must use a different scheme. This seems fairly clear given the context (note the word "also" for dir()), but to clarify, change the start of this paragraph from:

"Code that wishes to list all instance attributes generically"

to this (add the word "just"):

"Code that wishes to list just all instance attributes generically"

Mike Sweeney  Jun 06, 2011  Nov 04, 2011
Printed, PDF,
Page 792
third sentence

[Oct-13-10] Page 792, third sentence: main point lost by edit made during production

In this sentence, change the clause: "but they incur an extra method call for any accesses to names that require dynamic computation." to read as worded in my original text: "but they incur an extra method call only for accesses to names that require dynamic computation."

This clause describes how properties differ from tools like __getattr__, and the "only" in my original wording is really the main point. As changed by editors, that main point (the contrast that stems from their focus on a specific attribute instead of many) was lost.

While we're at it, please add page 792 to the Index entry for "property built-in function" -- this is a crucial first definition of them.

[from http://rmi.net/~lutz/lp4e-updates-clarifications-recent.html]

Mark Lutz
 
Oct 13, 2010  May 20, 2011
Printed, PDF,
Page 793
last 2 lines on page

[Oct-27-10] Page 793, last 2 lines on page, output lines missing in code listing

Somewhere along the way, we seem to have dropped 2 important output lines at the end of this listing (alas, this appears to have been propagated across multiple editions of the book). The text and code comments here and elsewhere describe __setattr__ behavior correctly, but the listing is misleading as is. To fix, change the very last two lines on this page which read:

>>> x.job = 'trainer' # Runs __setattr__ again
>>> x.job # Defined: no __getattr__ call

to the following, adding the 2 new output lines in non-bold font, and retaining the original spacing of the "#" comments on the right:

>>> x.job = 'trainer' # Runs __setattr__ again
set: job trainer
>>> x.job # Defined: no __getattr__ call
'trainer'

Mark Lutz
 
Oct 27, 2010  May 20, 2011
Printed, PDF,
Page 803
paragraph 2, end of line 3

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 803, paragraph 2, end of line 3: minor typo, "Object" should be "Other"

We need to replace "Object" with the actual class name "Other" in the sentence that ends on this line (an apparent slip of the virtual tongue). Change "though, it would update Object, not Spam! In this" to read "though, it would update Other, not Spam! In this".

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 805
end of second-last line on page

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 805, end of second-last line on page: minor typo, "next part" to "final part"

Change "to coding decorators in the next part of this book. As" to "to coding decorators in the final part of this book. As". (The next part of the book is exceptions, not advanced topics.)

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 813
very first line on page

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 813, very first line on page: minor typo, "Print" to "print" in error message

Change "Print(Spam.count)" to "print(Spam.count)" at the start of the very first line on this page. This is a code line which is part of a generated error message; it's shown correctly everywhere else here so this should be obvious, but merits a fix (MS-Word's auto-correction had a nasty tendency to uppercase code like this).

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed
Page 817
instructions for both exercise #2 and exercise #3 on this page

[Dec-14-09] Page 817, change "Mylist" to "MyList" in exercise instructions (minor detail)

In the instructions for both exercise #2 and exercise #3 on this page, replace all "Mylist" with "MyList", and replace all "MylistSub" with "MyListSub". (This refers to the 5 "Mylist" in #2, and the 3 "Mylist" plus 3 "MylistSub" in #3.) This way, the case in these names will match these exercises' solutions in Appendix B.

This is a very minor detail -- you can call the classes whatever you like, of course, and the names in the instructions are really just approximate suggestions (you won't lose points for changing case in one letter of a class name). On the other hand, this was a reader report, so the fix is warranted to make the instructions match the solutions completely. (This was originally reported as an errata for the 3rd Edition, where it also appears.)

--------
crossposted from http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 14, 2009  Jan 01, 2010
Printed
Page 818, 1126
title at the start of question number 4 (exercise question and its solution)

[Nov-12-09] Page 818 and 1126, "Metaclass methods" to "Attribute methods" (old terminology)

On both these pages (exercise and its solution), change the title at the start of question number 4 from "Metaclass methods." to "Attribute methods.".

This is a bit of a blast from the past; early on in Python, we used to call proxy (wrapper) objects having a __getattr__ "metaclasses", in deference to their delegation roles. Today, though, "metaclass" has a much different meaning, as described in Chapters 31 and 39 -- it's a way to control the class creation process. This exercise label has been present since the first editions of this book (over a decade ago), but has gone overlooked ever since the new metaclass model came online.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 820
exercises numbered wrong, #3 and #4

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 820, exercise numbers broken in production: #3 and #4 should be #8 and #9

Exercise numbering on this page was broken during production: numbers 3 and 4 here should be renumbered to be 8 and 9, as per my original final draft. Probably obvious to most readers, and these are numbered 8 and 9 correctly in the solutions appendix, but it's worth noting and fixing in reprints.

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF, , Other Digital Version
Page 842
start of paragraph 4

[Reposting this against the 4th edition: a reader originally filed it against the 3rd edition and it went unxfixed. Please delete this note if the original shows up.]

The "I ran this in a shell widow" should be "I ran this in a shell window".

Mark Lutz
 
Mar 30, 2012  May 18, 2012
Printed
Page 850
the 6th line in this page's note

Nov-12-09] Page 850, "raise E,V" is illegal in 3.0, not deprecated (broken by copyedit)

The book's copyedit process reworded some text in the note box on this page in such a way as to break its technical accuracy. To fix, change the start of the 6th line in this page's note from "deprecated in 3.0." to "deprecated in 2.6.".

Some background for people curious about the publishing process: This note describes the switch from "raise Exc, Args" syntax to "raise Exc(Args)", which is recommended in 2.6 but required in 3.X. Here's how the first part read when I submitted it to O'Reilly: " Python 3.0 no longer supports the raise Exc, Args form that is still available in Python 2.6. In 3.0, use the raise Exc(Args) instance creation call form used in this book instead. The equivalent comma form in 2.6 is legacy syntax for compatibility with the now defunct string-based exceptions model, and is deprecated. It is converted to the 3.0 call form if used. ".

When published, this text was changed by the editing process to the following -- a few tweaks for clarity, and one near the end that changed technical meaning in a subtle and critical way: " Python 3.0 no longer supports the raise Exc, Args form that is still available in Python 2.6. In 3.0, use the raise Exc(Args) instance-creation call form described in this book instead. The equivalent comma form in 2.6 is legacy syntax provided for compatibility with the now defunct string-based exceptions model, and it?s deprecated in 3.0. If used, it is converted to the 3.0 call form. ".

The last part of this implies that the comma syntax works in 3.0, but is converted to the new form. This is wrong. I also did not say this. It is the result of a wording change during copyedit which broke the original meaning after the book was submitted for publication. In this case, the edit seems unnecessary, and even logically unsound, given the rest of the description in this note (it happens; copy editors are not programmers, and vice versa). Since this change wasn't run past me explicitly, it was impossible to catch in the timeframe allowed for copyedit review. Unfortunately, this change did not just break grammar, it broke technical accuracy.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 896
end of second last paragraph

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-7-10] Page 896, end of second last paragraph: Unicode -- clarify impacts (new sentence)

At the very end of the paragraph which begins "Even if you fall into", add a new last sentence which reads: "Though applications are beyond our scope here, especially if you work with the Internet, files, directories, network interfaces, databases, pipes, and even GUIs, Unicode may no longer be an optional topic for you in Python 3.X."

I'm adding this because the existing text seems a bit misleading, after seeing firsthand how much Unicode permeates 3.X applications work. See this note for related discussion. Reprints: delete the first clause of this new sentence of it won't fit as is; it looks like there is plenty of room.

(This and 6 other Unicode items on this page arose from a recent reread of the Unicode chapter a year after writing it; it's fine as is, but a few key concepts could be polished with simple inserts in the next printing.)

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 898
Near the end of the second last paragraph

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-2-10] Page 898: Unicode -- mention UTF-16 and UTF-32 in intro (new text)

Near the end of the second last paragraph on this page, expand the start of the second last line by adding the parenthesized text in the following, to read: "sets in similar ways (e.g., UTF-16 and UTF-32 format strings with 2 and 4 bytes per each character, respectively), but all of these". This is implied by later UTF-16 examples, but UTF-16 is so common on Windows now that it merits a word here.

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 898
2nd bullet item on page

(Correction added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html)
------

[Jul-7-10] Page 898, 2nd bullet item on page: minor typo: "is' should be "its"

Another typo missed by all: At the end of the "Decoding" bullet's first line, change "into is character string" to "into its character string".

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 899
second bullet item in the second bullet list

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-2-10] Page 899: Unicode -- bytes is for encoded str too (new text)

At the second bullet item in the second bullet list on this page, add the following text in parenthesis at the end, so that the bullet item reads: "* bytes for representing binary data (including encoded text)". This is shown and implied in later examples, but this seems like a key link concept.

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 900
Add a footnote at the bottom of page 900

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-2-10] Page 900: Unicode -- internal str format (new footnote)

I avoided internals discussion in this chapter on purpose, using terms such as "character" instead, but in retrospect some readers might find a more tangible model useful too. Add a foonote at the bottom of page 900, with its star at the very end of the last paragraph before header "Text and Binary Files", which reads:

"It may help to know that Python internally stores decoded strings in UTF-16 (roughly, UCS-2) format, with 2 bytes per character (a.k.a. Unicode "code pont"), unless compiled for 4 bytes/character. Encoded text is always translated to and from this internal form, in which text processing occurs.".

Reprints: if this doesn't fit at the bottom of this page as is, please ask me how it could be shortened

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 901
start of 1st paragraph

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-7-10] Page 901, start of 1st paragraph on page: Unicode -- same policy for read, write (reword)

The start of this paragraph seems potentially misleading in retrospect--it's not clear if writes work the same as reads. This is clarified later on (see page 920 and later), but it may be worth tightening up here.

Change: "When a file is opened in text mode, reading its data automatically decodes its content (per a platform default or a provided encoding name) and returns it as a str; writing takes a str and automatically encodes it before transferring it to the file."

to read as this (the parenthesized part has been pulled out): "When a file is opened in text mode, reading its data automatically decodes its content and returns it as a str; writing takes a str and automatically encodes it before transferring it to the file. Both reads and writes translate per a platform default or a provided encoding name."

Mark Lutz
 
Jul 12, 2010  May 20, 2011
, Printed, PDF, , Other Digital Version
Page 902
footnote at page bottom (added in early reprint)

[Jan-4-12] Page 902: more on Unicode internal storage models

I inserted a short footnote at the bottom of Page 902 in reprints to describe the internal storage of Unicode characters in Python 3.X (per a July, 2010 note on my site). Because this is changing in 3.3, and because it looks like there is space on this page for elaboration, I want to change the footnote's current text:

"""
It may help to know that Python internally stores decoded strings in UTF-16 (roughly, UCS-2) format, with 2 bytes per character (a.k.a. Unicode "code pont"), unless compiled for 4 bytes/character. Encoded text is always translated to and from this internal form, in which text processing occurs.
"""

to read as follows (reprints: please ask me how to shorten if this is too large to fit at the bottom of the page, as it's not worth changing page breaks; this ideally should have been a sidebar, but it's too late for that much change):

"""
It may help to know that Python always stores decoded text strings in a encoding-neutral, multi-byte format in memory. All text processing occurs in this uniform internal format. Text is translated to and from an encoding-specific format only when it is transferred to or from byte strings, external text files, or APIs with specific ecoding requirements. Through Python 3.2, strings are stored internally in UTF-16 (roughly, UCS-2) format with 2 bytes per character, unless Python is configured to use 4 bytes/character. Python 3.3 and later will instead use a variable-length scheme with 1, 2, or 4 bytes per character, depending on a string's content. Either way, encoding pertains mostly to files and transfers; once loaded into a Python string, text in memory has no notion of encoding, and is simply a sequence of Unicode characters (a.k.a. "code points") stored generically.
"""

Mark Lutz
 
Jan 04, 2012  May 18, 2012
Printed, PDF,
Page 909
very end of the last paragraph on this page

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-2-10] Page 909: Unicode -- "conversion" means encoding differently (new sentence)

At the very end of the last paragraph on this page, add the following new sentence: "Either way, note that "conversion" here really just means encoding a text string to raw bytes per a different encoding scheme; decoded text has no encoding type, and is simply a string of Unicode code points (a.k.a. characters) in memory.".

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed
Page 910
the very end of the first paragraph on this page

[Nov-12-09] Page 910, printing 2.6 unicode, display of non-ASCII str can vary

At the very end of the first paragraph on this page, change: "(all other sections in this chapter are run under 3.0):" to "; unicode characters display in hex in 2.6 unless you explicitly print, and non-ASCII displays can vary per shell (most of this section ran in IDLE):". [Reprints: please ask me to shorten if this doesn't fit as is.]

[Discussion only follows -- no further reprint changes required]

I'm changing this because: (1) The original isn't quite correct -- there are other 2.6 sessions in this chapter; (2) The examples imply that echoes (repr) display hex for 2.6 Unicode, but "print" displays characters -- this isn't stated explicitly, though; and (3) The display of the first test in this section varies between IDLE and a DOS shell interface on Windows.

I ran this in IDLE and got the results shown in the text, but a non-IDLE user might be confused. Moreover, a later example gives the DOS display format, and this all differs in 3.X, where all strings are Unicode and always display characters:

# Python 2.6, in the IDLE GUI (same as shown in book)

>>> S = 'A\xC4B\xE8C'
>>> S
'A\xc4B\xe8C'
>>> print S
A?B?C
>>>
>>> U = u'A\xC4B\xE8C'
>>> U
u'A\xc4B\xe8C'
>>> print U <=== print in 2.X to show chars
A?B?C

# Python 2.6, in a Windows Command Prompt (DOS shell)

>>> S = 'A\xC4B\xE8C'
>>> S
'A\xc4B\xe8C'
>>> print S
A&#9472;B&#934;C <=== DIFFERS from IDLE display
>>>
>>> U = u'A\xC4B\xE8C'
>>> U
u'A\xc4B\xe8C'
>>> print U
A?B?C

# Python 3.1, in both interfaces (IDLE, DOS shell)

>>> S = 'A\xC4B\xE8C'
>>> S <=== no need to print() in 3.X
'A?B?C'
>>> print(S)
A?B?C
>>>
>>> B = b'A\xC4B\xE8C'
>>> B
b'A\xc4B\xe8C'
>>> print(B)
b'A\xc4B\xe8C'

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF,
Page 936
last sentence of page

(Clarification added for inclusion in reprints from
http://www.rmi.net/~lutz/lp4e-updates-clarifications-recent.html)
------

[Jul-7-10] Page 936, last sentence of page: Unicode -- mention filename tools too (new text)

Change the last part of the text: "For more details on re, struct, pickle, and XML tools in general, consult" to read: "For more details on re, struct, pickle, and XML, as well as the impacts of Unicode on other library tools such as filename expansion and directory walkers, consult".

The section here dealing with tools impacted by Unicode could also have mentioned that os.listdir returns decoded Unicode str for str arguments, and encoded raw binary bytes for bytes arguments, in order to handle undecodable filenames. In short, pass in the directory name as a bytes object to suppress Unicode decoding of filenames per the platform default, or else an exception is raised if any filenames fail to decode. Passing in a str invokes Unicode filename decoding on platforms where this matters.

By proxy, os.walk and glob.glob work the same way, because they use os.listdir internally to generate filenames in directories. This was omitted here because the section already encroaches on the language/applications line. Instead, the impacts of Unicode on these and other tools are covered in depth in the new 4th Edition of Programming Python, where application topics are collected in general.

Mark Lutz
 
Jul 12, 2010  May 20, 2011
Printed, PDF,
Page 944
last line of 2nd paragraph on page

[Sep-27-10] Page 944, last line of 2nd paragraph on page, minor text typo (broken by production)

Change "(you can the superclass in 3.0 too," to "(you can list the superclass in 3.0 too,". This was broken by an edit made during production; in my final draft, the original version read "(you can in 3.0 too," which was arguably ambiguous, but not grammatically incorrect!

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  May 20, 2011
Printed, PDF,
Page 956 and 976
pages 956 and 976 inserts needed to clarify

(Crossposted from http://www.rmi.net/~lutz/lp4e-updates.html for reprint inclusion)

[Sep-1-10] Page 976 and 956: Note that descriptor state cannot vary per client class instance

Add a new sentence at the very end of paragraph 3 on pge 976, which reads "The downside of this scheme is that state stored inside a descriptor itself is class-level data which is effectively shared by all client class instances, and so cannot vary between them.".

Also, after the first sentence of the last paragraph on page 956, add a new sentence which reads "Unlike data stored in the descriptor itself, this allows for data that can vary per client class instance.". It looks like there is space for both inserts, but please ask me how to shorten if not.

Rationale: There is an implication of descriptor state options which might have been called out more explictly than it was. Crucially, storing state in the descriptor instance instead of the owner (client) class instance means that the state will be effectively shared by all owner class instances. That is, because descriptors are class-level data, their content cannot vary per instance of client classes.

To see this at work, in the descriptor-based CardHolder example on page 976-977, try printing attributes of the "bob" instance after creating the second instance, "sue". The values of sue's managed attributes ("name", "age", and "acct") effectively overwrite those of the earlier object bob, because both share the same, single descriptor instance attached to their class:

class CardHolder: ...as is...

bob = CardHolder('1234-5678', 'Bob Smith', 40, '123 main st')
print(bob.name, bob.acct, bob.age, bob.addr)

sue = CardHolder('5678-12-34', 'Sue Jones', 35, '124 main st')
print(sue.name, sue.acct, sue.age, sue.addr)
# addr differs: cardholder instance data
print(bob.name, bob.acct, bob.age, bob.addr)
# name,acct,age same: descriptor data!

...> C:\Python31\python test.py
bob_smith 12345*** 40 123 main st
sue_jones 56781*** 35 124 main st
sue_jones 56781*** 35 123 main st

There are valid uses for descriptor state, of course (to manage descriptor implementation, for example), and this code was implemented to illustrate the technique. Moreover, the state scope implications of class versus instance attributes should be more or less a given at this point in the book. However, in this particular use case, attributes of CardHolder objects are probably better stored as per-instance data instead of descriptor instance data, perhaps using the same __X naming convention as the property-based equivalent to avoid name clashes in the instance.

Mark Lutz
 
Sep 01, 2010  May 20, 2011
Printed
Page 971
the start of the second code listing on this page

[Nov-12-09] Page 971, use "person.py" in shell command, not "getattr.py" (minor typo)

This is a very obscure typo (especially since the file name isn't given either), but to match later commandlines here, at the start of the second code listing on this page, change the first line from "C:\misc> c:\python30\python getattr.py" to "C:\misc> c:\python30\python person.py". This chapter generally assumes you know about files and shell commands already, but this is a bit inconsistent.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
PDF
Page 974
1st paragraph

re:
To understand this code, it's crucial to notice that the attribute assignments inside the
__init__ constructor method trigger property setter methods too.

python 2.6.5, linux

Stepping with pydev debugger through Attribute_validation_w_properties it appears
instance attribute assignments are only intercepted by properties for re-assignments, eg. bob.name = 'Bob Q. Smith' but not during instatiation since self._name remains 'Bob Smith" not "bob_smith" as setter implies. Correct ???

inside __init__ "name mangling" missing out and perhaps just one leading underscore ?

self._acct
self._name
self._age
self.addr

Excellent chapter though. For time I eventually managed to grasp the mysteries behind getter, setter etc and how they differ and start to get an idea what situation ea fit best.
Many Thanks
Mario Dix

Note from the Author or Editor:
No, the example does work as shown and described, and the "__name" attributes format is intended. However, this is arguably one of the most subtle examples in the book, so I'll try to clarify a bit here.

To see that the setter is indeed called for assignments in __init__ at instance creation time, try adding a print() in the setter methods,
and either run the self-test code or import the class and create an instance interactively:

class CardHolder...
def setName(self, value):
print('in setName')

>>> CardHolder('11111111', '25', 3, '44')
in setName
<test.CardHolder object at 0x01410830>

The setter is called from __init__ when the instance is first created and the attribute is assigned, under both Python 3.X and 2.X. Also make sure that you derive the class from "object" under 2.X to make it a new-style class. As explained earlier in this chapter (and in Chpater 31), property setters don't quite work under 2.X without including "object" in the superclass list; once an attribute name is mistakenly assigned directly on an instance, it hides the property getter in the class too (perhaps this was the entire issue here?):

class CardHolder(object): # required in 2.X

With this change results under 2.6 and 3.1 are identical. You'll also need to use 2.X-style print statements or a from __future__ for 3.X-style print calls; see earlier in the book for print() in 2.X:

from __future__ import print_function

The other oddness in this example (which is covered earlier in the book but perhaps not explained as explicitly for this example itself as it could have been) is that names beginning with 2 underscores like "__name" are pseudo-private attributes: Python expands them to include the enclosing class's name, in order to localize them to the creating class. They are used intentionally here to avoid clashing with the real attribute names such as "name" that are part of the class's external client API. Python mangles each in-class appearance of the attribute like this:

__name__ ...becomes... _CardHolder__name

The single underscore naming pattern "_name" used elsewhere in this chapter is a weaker convention that informally attempts to avoid name collisions, but "__name" truly forces the issue, and is especially useful for classes like this one which manage attribute access but also need to record real state information in the instance. Clients use "name" (the property), and the expanded version of "__name" (the data) where state is actually stored is more or less hidden from them. Moreover, unlike "_name", it won't clash with other normal instance attributes if this class is later extended by a subclass.

Thanks for your note and feedback; I'll mark this as "confirmed" so the clarification is available to others on O'Reilly's errata page.

Anonymous  Aug 21, 2010 
PDF
Page 995
bottom

Should "def decorate(O)" be "def decorator(O)" ?

Note from the Author or Editor:
Yes, change as described -- "decorate(O)" should be "decorator(O)". This is in pseudo/abstract/partial code so it's not too grievous, but it merits a fix nonetheless.

In the most recent printing (May 2011), this actually appears in the first line of the last code section on page 999, under heading "Decorators Manage Functions and Classes, Too".

Mike Sweeney  Jul 10, 2011  Nov 04, 2011
Printed, PDF,
Page 1001
last line of paragraph 4

[Sep-27-10] Page 1001, last line of paragraph 4, minor typo: "in" should be "is"

Change "class in not included in *args." to "class is not included in *args.". This typo was present in final draft, but missed by all proofreaders (including me).

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  May 20, 2011
Printed, PDF,
Page 1005
6th comment in "class wrapper" example code

# giveRaise = tracer(giverRaise)

should read

# giveRaise = tracer(giveRaise)

I suspect the the extra 'r' in 'giverRaise' is a typo.

Note from the Author or Editor:
Yes, please change as the poster directed (a minor typo in a code comment, but wrong as is nonetheless).

somerandomscreename  Oct 14, 2010  May 20, 2011
Printed
Page 1026
the section header line "Decorator Arguments."

[Nov-07-09] Page 1026, section heading is one level too deep

On this page the section header line "Decorator Arguments." was inadvertently coded as a level-4 heading, when it should be level-3 like all the other subheadings on this page. Not critical, but worth a fix.

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 1049
Chap 38, Answer 1: error in timer code which crosses from 1049-1050

Concerning Learning Python, 4th Edition, the code on page 1049 (chap 38, Answer to question 1) does not produce the "Expected output". Neither the code from the paperback which I typed in, nor the code which I downloaded produce the "Expected output" although they both generate the same output. For instance I get [CCC]==> listcomp: 0.00001. 0.00001, etcetera.

This second send includes the example.

Note from the Author or Editor:
[No fix required] Sorry, but I'm not sure what this post is referring to; the quiz question's answer code runs correctly and as shown. Its output under Python 3.2 and 2.7 are pasted below.

If the issue is that the timing numbers in the output (e.g., 0.00001) vary from those shown in the book, they are supposed to -- this timer script's code displays runtimes for decorated function and method calls, and actual per-call and total timing results will vary from machine to machine.

Also note that the output format for 2 lines will vary between Python 3.X (used in the book) and 2.X; these lines will have enclosing tuple parens and show greater precision in 2.X, because print is not a function call there. Print's version skew is well documented in the book and is assumed to be known by page 1050. To match 3.X output exactly in 2.X, you can always add a "from __future__ import print_statement" at the top of your script.

In any event, this does not qualify as an errata, and isn't a "serious technical mistake." If I have missed the point of this post, please follow up with more details, incuding the code as run and its full output produced.

...Output on my machine (your timing numbers should vary)...

c:\temp>c:\python32\python lp4e_q_38_1.py
[CCC]==>listcomp: 0.00002, 0.00002
[CCC]==>listcomp: 3.37414, 3.37417
[0, 2, 4, 6, 8]
allTime = 3.374168102870051

[MMM]==>mapcall: 0.00007, 0.00007
[MMM]==>mapcall: 6.13322, 6.13328
[0, 2, 4, 6, 8]
allTime = 6.133284282251598

giveRaise: 0.00009, 0.00009
giveRaise: 0.00005, 0.00014
55000.00000000001 120000.0
**lastName: 0.00013, 0.00013
**lastName: 0.00013, 0.00026
Smith Jones
0.00014 0.00026

c:\temp>c:\python27\python lp4e_q_38_1.py
[CCC]==>listcomp: 0.00002, 0.00002
[CCC]==>listcomp: 2.48429, 2.48431
[0, 2, 4, 6, 8]
allTime = 2.48430723795

[MMM]==>mapcall: 0.00008, 0.00008
[MMM]==>mapcall: 3.99012, 3.99020
[0, 2, 4, 6, 8]
allTime = 3.9901979759

giveRaise: 0.00004, 0.00004
giveRaise: 0.00003, 0.00007
(55000.00000000001, 120000.0)
**lastName: 0.00008, 0.00008
**lastName: 0.00015, 0.00023
('Smith', 'Jones')
0.00007 0.00023

Charles Wehrenberg  Nov 25, 2011 
Printed, PDF, , Other Digital Version
Page 1069
end of 2nd paragraph on page

I want to clarify that an __init__ in an application class is completely independent of an __init__ in an metaclass; the former runs at class construction time, and the latter at instance construction time, and not by the metclass's __init__. This is all implied by Python's class model (and should probably be intuitive at this point in the book), but to make this key point a bit more explicit, let's change this paragraph from:

"""
In this case, the class initialization method is run after the class construction method, but both run at the end of the class statement before any instances are made:
"""

to the following, adding just the parenthesized text at the end (and making its "Spam" and two "__init__" literal font):

"""
In this case, the class initialization method is run after the class construction method, but both run at the end of the class statement before any instances are made (conversely, an __init__ in Spam would run at instance creation time, and is not affected or run by the metaclass's __init__):
"""

Reprints: It looks like there are 2 free lines on this page, but let me know if this needs trimming to avoid changing page breaks.

Mark Lutz
 
Oct 30, 2011  Nov 04, 2011
Printed, PDF, , Other Digital Version
Page 1087
start of 4th paragraph in sidebar text on this page

I wish to change this sidebar's sentence:

"""
On the other hand, many new learners can pick up advanced topics as needed.
"""

to this:

"""
On the other hand, Python is still much simpler than most of its contemporaries and perhaps only as complex as its many roles require, and many new learners can pick up advanced topics as needed.
""""

This adds two crucial points -- that Python is still a lot simpler than Java, C#, or C++ today despite its growth, and that much of the recently added complexity might be warranted given its many application roles -- and in retrospect the sidebar may read a bit more negatively than intended without these, especially given its end-of-book appearance.

Reprints: It looks like there's room on the page for this, but please contact me if the insert makes the sidebar spill over onto another page (it should be shortened if so, but I'm guessing it takes up just 1 empty line on this page).

Mark Lutz
 
Oct 30, 2011  Nov 04, 2011
Printed
Page 1119
last paragraph on this page

[Dec-8-09] Page 1119, generator-based alternative to file counts exercise solution

If we have space, add the following sentence to the start of the last paragraph on page 1119: "A generator expression can have much the same effect: sum(len(line) for line in open(name)).", where the second half of this, "sum(...)", is code in fixed-width font.

[discussion follows -- no further reprint changes required]

I'd like to add this because this alternative generator solution is as nice as the one shown, though arguably less explicit:

# shown: loads into memory all at once, fails for large files

>>> len(open('README.txt').read())
7013

# shown: reads one line at a time with file iterators

>>> tot = 0
>>> for line in open('README.txt'): tot += len(line)

>>> tot
7013

# not shown: generator expression -- reads one line at a time, sums along the way

>>> sum(len(line) for line in open('README.txt'))
7013

# other part: using binary mode to match system size (keep Windows \r\n)

>>> sum(len(line) for line in open('README.txt', 'rb'))
7216
>>> import os
>>> os.path.getsize('README.txt')
7216

See Chapter 20 for more on generator expressions, and Chapters 4, 5, and 14 for sum(). sum() allows any iterable, and both the file iterator and generator expression in this alternative solution defer file line fetches until requested. The effect is to avoid an explicit for loop, and perhaps speed performance.

--------
This clarification was crossposted from the following web site:
http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Dec 08, 2009  Jan 01, 2010
Printed, PDF, , Other Digital Version
Page 1127
last sentence before start of #3

The entire sentence here:

"Also, note that sets are a built-in type in Python today, so this is largely just a coding exercise (see Chapter 5 for more on sets)."

seems to be out of place. No idea how it wound up here, but it's about the sets exercise, not operator overloading in general. Please move it to end of the first paragraph at #5 on Page 1130 instead. This should all read as:

"5. Set objects. Here?s the sort of interaction you should get; comments explain which methods are called. Also, note that sets are a built-in type in Python today, so this is largely just a coding exercise (see Chapter 5 for more on sets)."

Mark Lutz
 
Oct 29, 2011  Nov 04, 2011
Printed, PDF,
Page 1132
lines 5-7 on page

[Sep-27-10] Page 1132, lines 5-7: exception traceback gives prior 2.X version code+output

In the solution to the problem #3 of Part VII, the last 3 lines (lines 5-7 from the top of this page) should be changed from:

raise MyError, 'world'
hello: world
Got hello world

to read as follows:

raise MyError('Spam!')
oops.MyError: Spam!
Got Spam!

No idea how this slipped through the cracks (other than that this is a 1100-page book written on a typically crazy schedule, of course...). Most readers should be able to spot this by this point in the book, given that the error text and correct listed code don't match, but it merits a reprints patch.

*Note: please see the original webpage listed below for this item's code indentation, if it is munged when posted on this site.

[from http://www.rmi.net/~lutz/lp4e-updates-corrections-recent.html]

Mark Lutz
 
Sep 27, 2010  May 20, 2011
Printed
Page 1139
Entire index

In order to be useful as a reference manual (I read the entire book, now I need to refer to it) several items need to be added to the index. When I don't find something in the index when I am looking, when I eventually find it I write it in the index. Each of these are of this nature.

For each item, I give the text and the page numbers. Some index text is already present, the page numbers are added to the corresponding index entry.

* 133, 185, 284
** 189
% (formatting operator), 187
__all__ variable, 564
all, any, 364, 503
bool type, 322
classtools.py 665
dbm module, 216
diamond pattern of multiple inheritance trees, 778
eggs, 889
Emacs, 64
enumerate function, 358
environment variables, 1093
eval function, see also exec
Exception class, 830, 838, 858
exec function, see also eval
getattr, 661
import statement, as keyword, 566, 591
isinstance 468, 724
lock (thread), 853
min and max functions, 364
nop, see pass
operator precedence, 109
Perl 183
precedence, 109
private, 584, 720
regex, 85
singleton, 985
static methods, 753
strip, see rstrip
sys.exec_info, 854, 860
syst.exit, 883
threading, 853
traceback, 881
vars 183
with statement, 238
zip, 218

Note from the Author or Editor:
Thanks for your list. Although this book explicit describes itself as tutorial instead of reference, the Index could use some tweaking. It's gotten better in recent editions, but this has histrically been difficult to do well in the absence of reader feedback such as yours (O'Reilly does indexes itself as part of its production process).

I recommend adding as many of the items listed in this report as space allows, apart from the following exceptions and clarifications (which I hope format readably in O'Reilly's errata page):

--the "*" noted is for argument upacking, not the repitition operator (which is aready indexed).

--the '**' noted is for argument unpacking, not power (not indexed).

--"getattr" also should list page 592.

--"import statement, as keyword" should give the "as" in italics or quotes (that's the main point of this entry).

--"isinstance" should also include pages 101 and 250.

--"% (formatting operator)" should also include page 179.

--"regex" is already indexed with this page number under "re", the name of Python's regex module; instead, add a "regex, see re" entry.

--"sys.exit" is already indexed (though along with its argument too, unusually); your "syst.exit" looks like a typo.

--"Perl" doesn't appear on the page listed; it does on pages 18 and 20.

--"private" should also include page 1023, where a full-blown privacy implementation is hashed out.

The real limiting factor on these is the limited space we have for inserts in reprints; they can't shift page content much if at all. For what it's worth, I also wrote a book "Python Pocket Reference 4E"
to provide the quick lookup resource you may find useful after learning the basics.

Tom Ekberg  Jul 28, 2010  May 20, 2011
Printed
Page 1139
index additions list mia?

Reprints: a reader posted a nice list of Index additions which I added clarifications to and confirmed, but this post does not seem to be showing up here as far as I can tell. I saved the original--please ask me for it if you can't find this when updating for a reprint. --Mark Lutz

Mark Lutz
 
Aug 01, 2010  May 24, 2011
Printed
Page 1141
Add an entry to the index for bitwise ops

[Nov-07-09] Page 1141, Index, need entry for bitwise operations

The index really should include more about bitwise processing of integers; as is, there are links to page 108 for operator symbols only, but this is incomplete.

Add an entry to the index, "bitwise operators (binary data)", with links to pages "108, 124-125, 930-932". If this won't fit on the page, shorten the title to "bitwise (binary) data" and/or make the links "108, 124, 932".

--------
This item is part of a batch that was cut-and-paste from the
following webpage, which may contain additional information
about the issue:

http://www.rmi.net/~lutz/lp4e-updates.html

Mark Lutz
 
Nov 30, 2009  Jan 01, 2010
Printed
Page 1144
Left column halfway down

In the index distutils is misspelled as disutils.

Note from the Author or Editor:
Yes -- fix spelling as described. Apart from the index, it's spelled correctly everywhere else in the book.

cowboys85  Jul 26, 2010  May 20, 2011