[Core Python Programming]

Errata/Corrigendum

Last updated: $Date: 2008/02/22 10:35:56 $

PDF Versions (short versions do not have minor errata):

There will inevitably be errors when writing a book no matter how hard we try to keep it clean. In other words, "Don't (necessarily) believe everything you read!" A lot of hands touch the text before the book finally ends up in your hands, so here is where we try to clean it up. Even some of my own corrections found in the draft were not implemented due to lack of time or priority during the highly-compressed editing phase.

With regards to the corrections to the source code for the Examples in the book, MINOR problems do not prevent the script from running, but CRITICAL bugs means that the code printed as-is will not execute. We will provide changes or differences ("diffs") whenever possible. The diffs between the files are -u context diffs for those of you who know what they are. Because there is no other source for getting the code, all of the scripts for download have already been corrected.

If you find a new problem, send it to us at corepython (at) yahoo.com. Each errata item follows the format below... submit yours using the same format so that we can upload it faster to this page. We are also interested in hearing comments, suggestions, and general feedback, both good and bad. We want to continue improving the book for future readers and editions! MANY THANKS!!

Page(s) :: Section (may also have Figure, Table, or Example number) :: Subsection (if appl.) : correction

• Text which is in red indicates a change.
• Text which is in gray indicates an erratum that is of lower priority that is not normally displayed. Use the Toggle button below to swap between showing and hiding all minor errata.
• Normal priority errata denoted NEW or UPDATED were added/changed between Feb 2008 and May 2008 (even if we were notified earlier than those dates) along with appropriate credit(s) as necessary. We do not designate minor errata this way.


Text

FrontMatter

xxx :: Preface : Chapter Guide : Chapter 8 : In the first sentence, for, while, and if should be in Courier Bold font, as all keywords are.

xxxiv :: Preface : Book Resources : In the second sentence, add a comma between "errata" and "source code".


Chapter 1

1-2 :: 1 : The book is misnumbered... page "1" is missing. The final page of the Preface is xxxvii and jumps immediately to page 2 of the main body of text.

11 :: 1.4 :: Build It Yourself : The third step, make install will install the Python you just compiled and set it as the default Python interpreter. Should you wish to install multiple versions of the interpreter or do not wish to replace the existing version, use make altinstall. For example, if you have an existing Python 2.4.3 installtion then build and install 2.5 with make altinstall, calling python from the command-line still launches the 2.4.3 interpreter whereas to start 2.5, you would need to use python2.5.

17 :: 1.5.2 :: Unix : In the final paragraph of this section, we should also point out that executing $ script.py directly from the command-line only works if the current directory is part of your PATH environment variable. If it is not, you have to use ./ in front of the script name so that it can be found, e.g., $ ./script.py.

21 :: 1.5.4 :: Open Source : We inadvertently left out another popular IDE called Stani's Python Editor (SPE). The link to it: http://pythonide.stani.be/


Chapter 2

33 :: 2.1 :: Core Note : In the final part of this sidebar, when dumping the previous expression using the underscore, the output should be in quotes: 'Hello World!' (since the string itself is the expression and not its contents).

34 :: 2.5 : Just about the Core Note, we should warn the reader by adding the following as the final sentence of that paragraph: "Readers should be cautioned that users need to enter a valid Python integer when prompted for a number as anything other than such will cause int() to raise an error because it cannot convert the input into a valid Python integer."

37 :: 2.5 : In the second sentence of the final paragraph at the bottom of the page, change the -- to the unary negation sign - (single hyphen instead of two).

38-39 :: 2.6 : In the section preceding the call to decimal.Decimal(), we mention that "[you] must import the decimal module to use these types of numbers," but we didn't do so at the top of p. 39, so add the following at the top: >>> import decimal.

41 :: 2.10 : In the 2nd (and final) paragraph, change "***" to "device".

42 :: 2.11 : In the first print statement at the top of the page, there should be a space to separate "at" and "least".

43 :: 2.12 : The sequence in the first for loop should not wrap.

47 :: 2.15 : How to Open a File : The code near the top of this page does not correctly match the description below it. In fact, there should be two separate blocks of code. Add the following below the code but just above the para that starts with, "Rather than looping...":

      This script prompts the user for a filename, opens the file, and loops over the (text) file and displays one line at a time, and finally closes the file. This technique or idiom is simple to understand and works great, especially with large files because you do not need the entire file in memory at the same time. As an alternative for shorter files, take a look at this similar piece of code:

filename = raw_input('Enter file name: ')
fobj = open(filename, 'r')
data = fobj.readlines()
fobj.close()
for eachLine in data:
      print eachLine,

52 :: 2.18 : How to Create Class Instances : In the (first [John Doe]) sample output for calling foo1.showname(), the output should not have "__main__." in it. In other words, it should just be:

>>> foo1.showname()
Your name is John Doe
My name is FooClass


Chapter 3

68 :: 3.3.2 : Table 3.1 : The keywords as and assert should be in Courier Bold, like they are in the equivalent table in Appendix A on p. 1022.

80 :: 3.6 :: Example 3.1 : makeTextFile.py
The code for line 10 is missing. It should be fname = raw_input('Enter file name: ') and indented one level (at the same level as the line below it).

Even more importantly, our goal for keeping the text file platform-independent was defeated by the fopen() C library call on Win32 platforms. For each NEWLINE (\n or ASCII value 10) character encountered, it is replaced by the two Win32 line terminators RETURN (\r OR ASCII 13) and NEWLINE. This means that the original program created text files with \r\r\n between lines, a minor text file corruption and not our original intention.

The fix is to change the Python line terminator back to a solitary NEWLINE on line 30 and let the C library "do the right thing" for its respective platform. We apologize for any confusion caused for readers new to Python or cross-platform issues. Our original fix looked like this:

fobj.writelines(['%s\n' % x for x in all])

However, rather than process lines by adding a NEWLINE to each and sending the resulting list out to disk with the writelines() method, we preferred merging all of the text lines into a single string delimited by NEWLINE characters and performing a single write():

fobj.write('\n'.join(all))
(major patch [diff])

81 :: 3.6 : Core Tip : The word "lookup" should be in normal roman font, not Courier.

82 :: 3.6 : Lines 28-32 : Due to the change in the code for Example 3.1 above on p. 80, these two paragraphs need to be replaced with:

Now that we have the entire contents in memory, we need to dump it to the text file. Line 29 opens the file for write, and line 30 writes each line to the file. Every file requires a line terminator (or termination character[s]). The '\n'.join(all) takes each line of all (list of input strings), and join()s them together into one large string delimited by the NEWLINE character. That single string is then written out to disk with the file object's write() method.

85 :: 3.8 : Exercises 3-6(b) : Shorten part (b) to read, "What do each contain after...."

85 :: 3.8 : Exercises 3-7 : The spacing gap between the 1st row of potential identifiers is greater than for the remaining rows. It should be reduced to match the rest.


Chapter 4

93 :: 4.3.2 : Core Note : Boolean values : The bullet points for the numeric types (4 thru 7) should be indented.

100 :: 4.5.2 : Core Note : Interning : In the second to last paragraph, it is stated that the cached integers are in the range(-1, 100). As of Python 2.5, that has been expanded to range(-5, 257).

102 :: 4.6 : Table 4.4 : All instances of obj in the "Function" column should be in italics.

104 :: 4.6.3 : Core Note : It is likely that the back ticks (` `) will be deprecated in a future version of Python (say 3.0).

105 :: 4.6.4 : The comment for the class Foo definition should say that is is a classic class definition (not a new-style class).

110 :: 4.6.5 :: Table 4.5 : isinstance() is missing from the built-in functions section of this table. The two possible syntaxes are: isinstance(obj, cls) and isinstance(obj, (cls1, cls2,... clsN)). The description should read, "Determines whether an object is of a certain type or class of types." Finally, it returns a bool. Also, the description for type() should be changed to: "Returns given object's type object".

116 :: 4.9 :: char or byte : Python 3.0 will have a byte type and perhaps some of the later 2.x releases.

118 :: 4.10 : Exercise 4-9 : The answer to part (b) will differ starting with Python 2.5 (vs. all previous releases). What if c and d were given the value 500 instead?


Chapter 5

132-133 :: 5.5.3 : Modulus : We neglected to give a proper example of using the modulus operator. Add the following to the end of the subsection: "The modulus operator in Python is like that of C, the percent symbol (%), and here are some examples of using it:
>>> 5 % 2
1
>>> 8 % 4
0
>>> 6j-7 % 3
(-1+6j)

NEW -- Thanks to Greg Nofi (May 07) and Mark Ackerman (Jan 08)
133 :: 5.5.3 : Exponentiation : In the final code snippet, we showed an error when raising a number to a negative power. As of Python 2.2, the operands are correctly cast to floats as well as the result (this applies to both the ** operator as well as pow()):

>>> 4 ** -1
0.25

153-154 :: 5.9 : Exercises 5-9 and 5-17 : There is an extra space in exercise 17 between the 2**31 and the -1. It should be 2**31-1. The extra space needs to be put between the 017 and the + in the 2nd example of exercise 9(a), as in >>> 017 + 32.


Chapter 6

167 :: 6.1.3 : Table 6.3 : Footnote "d" for zip() should be in roman font, not Courier.

173 :: 6.3.2 : Membership (in, not in) : The string data attribute names have changed. string.uppercase, string.lowercase, string.letters all have Unicode characters now. To get the pure ASCII versions, use string.ascii_uppercase, string.ascii_lowercase, string.ascii_letters.

173 :: 6.3.2 : Example 6.1 : Line 1 is missing the (root directory) first forward slash in the *ix start-up directive; it should be, #!/usr/bin/env python, and line 5 should refer to string.ascii_letters.

173-174, 246, 1014 :: 6.3.2, 6.2.2, Appendix A : Example 6.1, Exercise 6-2, Answer to Exercise 6-2 : An extraordinary amount of emphasis is placed requiring possible identifier strings to be longer than one character in length when it is not absolutely necessary (as you are probably aware). The first part of Exercise 6-2 is not a "trick question" nor is changing the length check artificial. More of an emphasis should be placed on the 2nd half of the exercise instead. The solution given in Appendix A can be replaced by a simpler solution (which can be downloaded here).
#!/usr/bin/env python

from keyword import kwlist
import string

ALPHAS = string.ascii_letters + '_'
NUMS = string.digits

def main():
    print 'Welcome to the Identifier Checker v2.0'
    myInput = raw_input('Identifier to test? ').strip()

    if len(myInput) == 0:
        print "ERROR: no identifier candidate entered"
        return

    if myInput in kwlist:
        print "ERROR: %r is a keyword" % myInput
        return

    alnums = ALPHAS + NUMS
    for i, c in enumerate(myInput):
        if i == 0 and c not in ALPHAS:
            print 'ERROR: first symbol must be alphabetic'
            break
        if c not in alnums:
            print 'ERROR: remaining symbols must be alphanumeric'
            break
    else:
        print "okay as an identifier"

if __name__ == '__main__':
    main()

NEW (May 08)
184 :: 6.4.4 : This section refers to Section 6.7.4 as that for Unicode when it should refer to Section 6.8 instead.

188-190 :: 6.22 : Table 6.6 : The string.{center,[rl]just}() methods now take a fillchar=' ' argument where fillchar is the character to use for padding. It should have a (new) footnote "g": "New or changed in in Python 2.4."

189-190 :: 6.22 : Table 6.6 : The string.*strip() methods now take a chars=[ \t\n\v\f\r] argument where chars can be any sequence of leading and/or trailing characters to remove. It should have a (new) footnote "f": "New or changed in in Python 2.2.2."

190 :: 6.22 : Table 6.6 : The string.rsplit(str=' ', num=string.count(str) method is missing: "Same as split(), but search backward in string." It should have a (new) footnote "g": "New or changed in in Python 2.4."

190 :: 6.22 : Table 6.6 : The signature for string.splitlines() is incorrect. It should be: string.splitlines(keepends=False): "Splits string at all NEWLINEs and returns a list of each line with NEWLINEs removed unless keepends=True.

199 :: 6.8.3 : The last few sentences of the first complete paragraph on this page are erroneous now. The string module was updated with Unicode equivalent constants as well as the new string templates as described earlier in section 6.4.2 on p. 182. The paragraph should end with the final sentence, "Both behave very similarly."

204 :: 6.8.8 :: Unicode Type : "basestring" should be in Courier/mono font.

219 :: 6.13.2 :: sum() : In this section, the code example references the reduce() built-in function. For more details on reduce(), read ahead to section 11.7.2 in Chapter 11.

UPDATED (May 08)
232 :: 6.16 :: How to Create and Assign Tuples : Change "empty tuples" in the first paragraph to "tuples with only one element" -- see the example below with emptiestPossibleTuple which is also inappropriately-named since it is a tuple of a single element, not very empty at all. Empty tuples are specified with just a pair of parentheses: ( )

240 :: 6.19 : Fix this typo in the final paragraph of this section at the top of the page: "... also contains the same for sequence types." (This refers to the functional equivalents to sequence type operators.) Also, the final three sentences (with the first beginning with, "Finally,...") SHOULD BE REMOVED as Python now does support subclassing of the standard types.

247-248 :: 6.22 :: Exercise 6-7 and "Example 6.4" : buggy.py is really Example 6.5. (Example 6.4 is queue.py back on p. 229.) This is just a minor detail. The real problem is that in lines 11 and 27 of buggy.py, the references to fac_list erroneously use single quotes. In other words, it should be using backticks or repr(), i.e., `fac_list` or repr(fac_list). This was NOT a typo in the First Edition however.

250 :: 6.22 :: Exercise 6-18 : The subtitle of this problem should read, "zip() Built-in Function." and refers to the reading in Section 6.13.2.


Chapter 7

266 :: 7.4 :: Table 7.2 : The second entry should be dict.copy() not dict.clear(). Also, both the "*" in dict.iter*() and the "None" in dict.setdefault() should be in Courier/mono font. None of these errors are present in (the equivalent) Table B.9 on p. 1035.

267 :: 7.4 : In the first sentence of the second paragraph (right below the code snippet), "directory" is the wrong word and should be changed: "... add the contents of one dictionary to another."

NEW (May 08)
286 :: 7.12 :: Exercise 7-5 : In exercise 5(c), the parenthesized list should remove reference to the now-obsolete rotor module and add in a few new ones. It should be replaced with: "(see the getpass, md5, crypt [Unix-only], hashlib [2.5], and other cryptographic modules)."

288-289 :: 7.12 :: Exercises 7-13 - 7-15 : In all 3 problems, all references to sets A and B should be in Courier/mono font, including any operators in between.

Chapter 8

295 :: 8.4 : Guido's name was messed up in the 1st and 3rd paragraphs during the final editing phase of the manuscript. Read as only "Guido" or "van Rossum", not "van Rossum Guido"[sic].

303 :: 8.6.5 : There is a misspelling of "returning" in the final sentence of this paragraph. Also, so readers don't have to hunt for the reference, the final sentence should end with, "... similar to views as discussed in the previous chapter at the end of Section 7.4."


Chapter 9

327 :: 9.2 : Table 9.1 : Footnote "A" : Universal NEWLINE Support (PEP 278) was added in Python 2.3 not 2.5.


Chapter 10

376 :: 10.3.7 :: Example 10.1 : cardrun.py
The original installed script was out-of-date. Please download a new one if your file is older than 2007 Jan 1. We also installed the example carddata.txt file as listed on p. 375 as well as updated the alternate version in the alt directory. (critical patch)

377 :: 10.3.7 :: Line-by-Line Explanation :: Lines 36-37 : The cat cardlog.txt command-line has an extra space that should not be there.

384 :: 10.4.2 :: Context Expression, Context Manager : Italicize with_suite in the only paragraph on this page.

387-389 :: 10.6.1 including Table 10.1 : Italicize all the variables, such as with_suite, args, traceback, instance, exclass, tb.

380-381 :: 10.3.10 : In the pair of examples using try-finally, if the open() call fails, ccfile will be undefined, resulting in a NameError exception being thrown, an insult to injury on top of the IOError exception we received for the failure in open(). The usual idiom to avoid this situation is by setting ccfile = None before the try-finally, then add an if ccfile: before calling close(), as in:
ccfile = None
try:
    try:
	ccfile = open('carddata.txt', 'r')
	txns = ccfile.readlines()
    except IOError:
        log.write('no txns this month\n')
finally:
    if ccfile:
        ccfile.close()

and

ccfile = None
try:
    try:
	ccfile = open('carddata.txt', 'r')
	txns = ccfile.readlines()
    finally:
	if ccfile:
	    ccfile.close()
except IOError:
    log.write('no txns this month\n')

386, 394 :: 10.5, 10.8 : In the final paragraph for section 10.5, we describe the obsolescence of string exceptions. The raising exceptions in Python 2.5 resulting in a warning can be further clarified that it will no longer be allowed in 2.6. Similarly, the catching of string exceptions results in a warning beginning in 2.6 but will not be allowed in 2.7.
This clarification can also be carried to the second-to-last paragraph of section 10.8. It is erroneously stated that raising of string exceptions is not allowed in 2.5, which it is allowed but generates a warning. Similarly for the catching of string exceptions, it's really only disallowed starting in 2.7; in 2.6, a warning is generated.

390 :: 10.7.1 : With regards to the __debug__ system variable, after Python 2.2, rather than having values of 1 and 0, it is a Boolean, thus have values of True and False, respectively.

391-393 :: 10.8 : Table 10.2 : Various editing errors exist in the table of standard exceptions:
      • (391) The 2nd entry for SystemExit should have a footnote of "b" just like it is in the entry above. The entire row should also be grayed out, indicating the change that occurred back when Python 2.5 was released.
      • (392) (The 2nd entry for) KeyboardInterrupt should have a footnote of "c" just like it is in the entry on the previous page. The entire row should also be grayed out, indicating the change that occurred back when Python 2.5 was released.
      • (392) TabError should be indented... it is derived from IndentationError.
      • (393) UnicodeTranslateError should have a footnote of "i" (not "f").
      • (393) PendingDeprecationWarning should be one word.
      • (393) Footnotes "b" and "c": the word "subclassed" should be "derived from".
      • (393) Footnote "f" is a duplicate of "h" and SHOULD BE REMOVED. All remaining footnotes and corresponding tagged text should be adjusted accordingly.

395-397 :: 10.9 :: Example 10.2 : myexc.py
Line 77 is missing the full function call using the module name: tempfile.mktemp(). Also, since file() is now a factory function, we've renamed all such named references to fn. Finally, enter your own hostnames on line 101 rather than using our test lab computers which certainly won't work for you. (critical patch)

405 :: 10.14 : Exercise 10-5 : All five subproblems [parts (a)-(e)] should be aligned (flush) towards the left so that part (b) does not wrap. Also, the Python prompt for part (e) should not be in bold.

Chapter 11

413 :: 11.2.2 : Near the top of the page, in the calls to foo, both the standard calls as well as the keyword calls should be aligned properly.

414 :: 11.2.4 :: Example : In the 2nd paragraph, remove the space in "binary operators/ operations".

417 :: 11.2.4 :: Line-by-Line Explanation :: Lines 30-41 : We got a little ahead of ourselves in the example output. Example 11.1, easyMath.py, only supports addition and subtraction. The code output demonstrating multiplication is a result of implementing Exercise 11-16 on p. 474, so you should discard all such output until you have completed a working solution to that problem.

NEW -- Thanks to Tony Tang (May 08)
434 :: 11.6.1 : In the code snippet featuring tupeVarArgs(), the 2nd print statement should refer to arg2 and not arg1, as in:
print 'formal arg2:', arg2.

443 :: 11.7.2 :: Figure 11-1 : The "0" and "1"s inside the box representing the boolean function bool_func() should instead be represented by the Boolean values False and True, respectively. Those values will be integers only prior to Python 2.3.

444 :: 11.7.2 :: filter() : The 2nd paragraph (right beneath the code snippet) mistakenly refers to having two functions, one of which is main(). (We removed this function, pushed the body out to the global part of the code, and did not update the text. Rewrite this paragraph as:

This code snippet contains a function odd() which returns True if the numeric argument that was passed to it was odd and False otherwise. The main portion of the snippet creates a list of nine random numbers in the range 1-99. [Note that random.randint() is inclusive and that we could have used the equivalent random.randrange(1, 100), which we recommend because it has the same calling convention as the built-in function range().] Then filter() does its work: call odd() on each element of the list allNums and return a new list containing just those items of allNums for which odd() returned True, and that new list is then displayed to the user with print.

465 :: 11.8.5 : Just before the middle of the page, in the final definition of foo(), the calls to bar() should not have any arguments. We stated immediately above how the previous code snippet required altering those calls to take a parameter which was not desired.

469 :: 11.10.1 : In the code snippet in the middle of the page, we should have used random.randrange(), not random.randint() as the latter will give an error if the random index chosen is the length of the list. randrange() has a similar syntax to range() meaning that it goes up to but does not include the (second or only) index. Also, the checking of the sequence length is unnecessary as it will return False if it is empty. Given these changes, we can shorten the code to the following:

from random import randrange as rr

def randGen(aList):
    while aList:
	yield aList.pop(rr(len(aList)))

Finally, all three of the code snippets used in this subsection can now be downloaded here (as of Dec 6).

470 :: 11.10.1 : In the final sentence of the 2nd paragraph, "you" is the wrong word and should be changed: "Without generators, your application code...".

474 :: 11.11 :: Exercise 11-13 : Reword part (c) to: Discard mult() and use lambda instead.


Chapter 12

485 :: 12.4.4 : In the section title, "Import" should be in regular roman (italicized) font, not Courier Italic.

488 :: 12.5.4 : The final sentence of the second paragraph features a misspelling of impter.py filename.

494 :: 12.7.1 : Towards the end of this section, the reference to __init__.py is horribly misspelled.

495 :: 12.7.4 : At the bottom of the page when importing G3.dial, there is an extra trailing "." that SHOULD BE REMOVED.

502 :: 12.10 : Exercise 12-6 : Resolving various spacing issues in the example call, we get: newname = importAs('mymodule').


Chapter 13

508 :: 13.1 : Missing a word in the 3rd paragraph which should read, "...because there would be no references...."

515 :: 13.2.1 : The 2nd to last sentence in this section should end with "OOD" instead of "OOP", otherwise it reads like infinite recursion, or "Mr. Bunny's Guide To Java". :-)

520 :: 13.4.1 : Since this section is optional (as per the previous section), there should be a "*" in front of the subsection title.

524 :: 13.4.4 : Under Table 13.1, the first paragraph should start with the following: "In addition to the __dict__ attribute of the class MyClass we just defined above, we have the following:". Also, the print statement for MyClass.__dict__ SHOULD BE REMOVED since we already displayed the contents of the dictionary for both new-style and classic classes in the immediately preceding subsection (on the previous page).

NEW -- Thanks to Adil Lotia (Oct 07) and Satoshi Tanabe (Apr 08)
530 :: Core Note : All references to InstCt should be changed to InstTrack to match the output below.

543 :: 13.8.1 : In the TestStaticMethod example, the call foo = staticmethod(foo) should be dedented to the same level as the definition of the foo() function, e.g.,

class TestStaticMethod:
    def foo():
	print 'calling static method foo()'
    foo = staticmethod(foo)

553 :: 13.11.3 : In the SortedKeyDict example output, the supposedly sorted list when using keys() is out-of-order due to an error correction: "xin-yi" was misspelled as "hsin-yi", and the edit was made without reordering the list correctly. it should be:

By keys(): ['hui-jun', 'xin-yi', 'zheng-cai']

577 :: 13.13.2 :: Example 13.3 : time60.py
The documentation string for __init__() on line 7 should indented one level (four spaces to the right).
(minor patch)

586 :: 13.14 :: Single Underscore ( _ ) : Remove the "we" in the 2nd half of the final sentence on this page.

603 :: 13.16.4 :: Descriptor Examples : In the middle of the page, the sentence that starts with, "Our final example...," should refer to Example 13.9 on the next page. Otherwise, you may think that it refers to the previous code snippet.

603 :: 13.16.4 :: Descriptor Examples and Example 13.9 :: Lines 28-39 : The final sentence of this paragraph has several problems. Rewrite as: "Note that if you are using Python older than 2.5, you cannot merge the try-except and try-finally statements together (lines 30-38)."

604 :: 13.16.4 :: Example 13.9 : descr.py
For this code to work with Python 2.5 and newer, delete line 31. For this code to work with any version of Python, indent line 34 one level (four spaces to the right). For the __set__() method, the open() statement on line 29 should really be moved to the innermost try block immediately below it (between lines 31-32), and the succeeding except should also be monitoring for IOError — just like in the above __get__() method. Less importantly, name should not not have a default value as it does now on line 9. Below, we post two patches, one for users of Python 2.5 and newer as well as one for those using Python 2.4.3 and older.
(critical patch [diff]; pre-2.5 patch [diff])

607 :: 13.16.4 : Properties and property() Built-in Function : The last part of the final sentence in the first complete paragraph at the top of the page before the definition of the ProtectAndHideX class should be changed to the following: "... encrypting it by using the bitwise complement operator:". (The XOR operator is binary and not used in this example.)

609 :: 13.16.4 : Properties and property() Built-in Function : I must have done this really late at night as the code for the HideX class will not work with using the property() factory function as a decorator (in any version of Python). You will always have to use the x = property(**x()) syntax. Likewise, the text of Exercise 13-21 on p. 625 has to be changed (see below). The reason why it does not work is because the defition of x() will not automatically return the inner function objects so that the property can be created. That's why you still need to execute x() in order to get it to call locals() so that the fget() and fset() names and objects are returned. How these objects help create the property is still the main point of Exercise 13-21. In the code, remove the @property decorator and add x = property(**x()) right beneath the function declaration. Let's also change the class name to something more appropriate for this example:

#!/usr/bin/env python
'ProtectAndHideX.py -- protect the "x" attribute'

class ProtectAndHideX(object):
    def __init__(self, x):
        self.x = x

        def x():
            def fget(self):
		return ~self.__x

            def fset(self, x):
                assert isinstance(x, int), \
                    '"x" must be an integer!'
                self.__x = ~x

            return locals()

        x = property(**x())

inst = ProtectAndHideX(10)
print 'inst.x has a value of:', inst.x
inst.x = 20
print 'inst.x has a value of:', inst.x
inst.x.fset(40)   # sorry!
print 'inst.x has a value of:', inst.x

You can download this code here. The output of executing the code above will look like this:

inst.x has a value of: 10
inst.x has a value of: 20
Traceback (most recent call last):
  File "", line 1, in ?
  File "ProtectAndHideX.py", line 22, in ?
    inst.x.fset(40)   # sorry!
AttributeError: 'int' object has no attribute 'fset'

In the final paragraph on this page, keep only the first sentence, beginning with, "Our code works exactly as before...." Drop the final 2 sentences.

618 :: 13.18 :: Exercise 13-3 : In the preliminary work paragraph, there is a missing single closing quote for the string '$1,234,567.89', and that string should be in Courier/mono font.

UPDATED (May 08)
619 :: 13.18 :: Example 13.11 : moneyfmt.py
Line 13 of __repr__() should be replaced with a call to repr(), i.e.,
def __repr__(self):
    return repr(self.value)
The original code, including the source in the download area, has return `self.value` which is still valid for now, but the single backticks will be deprecated some point by repr().

621 :: 13.18 :: Exercise 13-7 : There should be an extra space in the final sentence separating "to" and "Exercise 6-15".

622 :: 13.18 :: Exercise 13-9 : The descriptions of the enqueue() and dequeue() functions refer to modifying a "list" when it should be "queue." Also, this problem refers to Example 6.3 for motivation, but it should really be Example 6.4 instead.

625 :: 13.18 :: Exercise 13-20 : The font for the first and last lines of code in part (f) are oversized and should be shrunk to match the remaining lines of code. Also, add a part (g) which reads, "(g) Can we move the math-oriented code out of __add__() and into one of the other methods of this classfile? If so, which one and why would it make sense to do so?

625 :: 13.18 :: Exercise 13-21 : Like the errata above for the code on p. 609, the use of property() as a decorator does not work for any version of Python. There is also multiple typos in the "alternate syntax" (which turns out to be the only syntax that can be used). This problem should be completely rephrased as:

Toward the end of section 13.16.4, we used the syntax x = property(**x()) to create a property for the x attribute for the HideX class. How does this idiom, including the enclosed call to x(), actually create the property?


Chapter 14

630 :: 14.1 :: "lambda Expressions" : In the (sub)section title, "lambda" should be in normal roman font, not Courier.

644-645 :: 14.3.6 :: Creating Code at Runtime and Executing It : For those unfamiliar with the C shell and its descendants, you can change the % prompt to that of sh/bash: $. The first one is misindented too far... move it to the left to align it with the rest of the program output.

648 :: 14.3.6 :: Conditionally Executing Code :: Example 14.2 : Lines 24 and 29 are not indented properly... indent them further to the right.

649 :: 14.3.6 :: Line-by-Line Explanation :: Lines 18-29 : There is an extra blank line in the program output... remove it.

650 :: 14.4.1 :: Core Note : def foo... should really be def bar....

651 :: 14.4.1 : The print statement for import2.py needs to be indented to the right one more space.

652 :: 14.4.1 : In the final paragraph eval() should not be italacized.

657 :: 14.5.2 : In the (sub)section title os.popen() should be in Courier font.

661 :: 14.5.5 : The reference to os.system() at the top of the page should not be in boldface. Also, in the code for the "Replacing os.system()" section, remove the superflous import os line completely.

663 :: 14.7.1 : SystemExit in the second-to-last sentence on this page should be one word.

664 :: 14.7.1 :: Example "14.4" : Globally replace "14.4" with "14.3" ... there is no Example 14.4.

UPDATED (May 08)
668-669 :: 14.10 :: Exercise 14-1 : There should be 13 exercises in this chapter:

669 :: 14.10 :: Exercise 14-9 (14-11) :: Extra Credit 1 : The "os" module name should be in Courier font.

669 :: 14.10 :: Exercise 14-9 (14-11) :: Extra Credit 2 : The "-ef" argument of the functional style call should be parenthesized, as in: sort(grep(ps(-ef), root), -n, +1).

669 :: 14.10 :: Exercise 14-11 (14-13) : The example referred to is incorrect as per erratum above for p. 664. funcAttrs.py is Example 14.3.


Chapter 15

697 :: 15.3.13 :: Example 15.1 : rewho.py
f.readlines() can be shortened to the file iterator f.
(minor patch)


Chapter 16

719-720 :: 16.3.2 :: Table 16.1 : It would be nice if the 2nd column were reduced in size so that the methods in the 1st column don't wrap.

729 :: 16.3.7 :: Example 16.4 : tsUclnt.py
Line 20 should simply be print data
(critical patch)

734 :: 16.4.1 :: Example 16.5 : Line 13 has a font size issue.

740 :: 16.5.2 : In the 2nd paragraph, remove the hyphen from the call to clientConnectionFailed().

742 :: 16.6 : Replace the final part of the final sentence with, "... we strongly encourage you to read ahead to Chapters 17 and 20."

NEW (May 07)
742 :: 16.7 :: Exercise 16-5 : The URL for the socket example has changed to
http://www.python.org/doc/current/lib/socket-example.html

745 :: 16.7 :: Exercise 16-14 : In the final portion of the exercise, change "i.e." to "e.g.".


Chapter 17

749 :: 17.2.2 : Figure 17-1 : The diagram was not drawn correctly to specification. Here are some fixes to repair it:
  1. Make the FTP client box bigger and make the FTP server box smaller so they are nearly the same size... there is no size differentiation between client and server, so the diagram should reflect that.
  2. Move "M (> 1023)" left just above the top solid line connecting the FTP client box and the Internet cloud, symmetric to where "M + 1" is below the bottom solid line.
  3. Move "ctrl/cmd" down so it's just above the top dashed line inside the Internet cloud
  4. Move "data" to be centered just below the bottom dashed line inside the Internet cloud
  5. Change "20 or" to "20 [active] or"
  6. Change "N (> 1023)" to "N (> 1023) [passive]"
  7. Delete "(Active)(Passive)"

754 :: 17.2.6 : Example 17.1 : Line-by-Line Explanation : Lines 11-44 :

  1. (middle paragraph) Add one more sentence: "After the transfer has completed, we would then call loc.close()."
  2. (final paragraph) Strike "if it is there": "...we remove the empty file if it is there to avoid clutter...".
  3. (final paragraph) Add a new second-to-last sentence: "We should probably put some error-checking around that call to os.unlink(FILE) in case the file does not exist."
  4. (final paragraph) Change the final sentence to: "Finally, to avoid another pair of lines (lines 43-44) that close the FTP connection and return, we use an else clause (lines 35-42)."

755 :: 17.2.7 : In the first paragraph after the bullet points, "creating" should be changed to "created".

757 :: 17.3.3 : The first paragraph after the list of steps is missing a word: "...carbon copy of using the FTP protocol."

758 :: 17.3.4 : Table 17.2 : In the entry for "xhdr", move the "[" back two characters, to, xhdr(hdr, artrg[, ofile])

759 :: 17.3.5 : In the line of code that starts with, ">> Rounding like this...", remove one ">" so that it is "> Rounding like this..."; also, it appears either this line or the line above it has the wrong paragraph tag as there is a gap between these two lines... it should be single-spaced like all the others.

762 :: 17.3.6 : Example 17.2 : Line 60 : Not really a correction but a note that Generator Expressions were added in Python 2.4, so if you are using 2.0-2.3.x, you will need to switch it to a List Comprehension by changing the parentheses to square brackets.

765 :: 17.3.6 : Example 17.2 : Line-by-Line Explanation : Lines 57-80 : At the top of this page following the first paragraph of this section which began on the previous page, insert the following new paragraph which explains line 60.
Line 60 is a generator expression. It works like a list comprehension only it does lazy evalution and does not build the entire results list when this line is executed. (The entire dataset, data, is already taking enough memory as it is!) Rather, each line is only processed when its turn comes up in the loop below on line 62. Generator expressions were added in Python 2.4, so if you are using an earlier release, the easiest fix while minimizing memory use is to add a new statement in between lines 62 and 63: line = line.rstrip(). If memory is not a concern, then just use a list comprehension instead (change the parentheses to square brackets).

772 :: 17.4.8 : Figure 17-3 : The not-well-arranged text on the second MUA down on the left should read, "IMAP4/POP3 (receive)", similar to the one for the bottom MUA as well as the one on the far right.

773 :: 17.4.9 : Add a mention of secure mail retrieval by splitting up and updating the final sentence: "Before we take a look at a real example, we should mentioned that there is also a poplib.POP3_SSL class which will perform mail transfer over a secure connection provided the appropriate credentials are supplied. Let's take a look...."

784 :: 17.6 : Exercise 17-28(a) : Not really a correction, but add a... "Hint: see the mailbox module and email package."


Chapter 18

801 :: 18.5 : Core Tip : In the 3rd paragraph, the setDaemon() method name should not have a hyphen/dash.

802 :: 18.5 : Table 18.3 : There shouldn't be any spaces around the = for the join() method's arguments.

811 :: 18.5.6 : Table 18.5 : The table describing the attributes of the Queue module is missing a few items and needs to be updated... stay tuned for the exact corrections/updates.


Chapter 19

NEW (May 08)
833 :: 19.3.5 :: Line-by-Line Explanation :: Lines 1-18 : The functional module is renamed to functools. 834-835 :: 19.3.6 :: Example 19.6 : Lines 15 and 17 should be indented like the rest of the lines in the __init__() method.

851 :: 19.6 :: Exercise 19-2 : Replace "windows" with "widgets". 851 :: 19.6 :: Exercise 19-4 : HINT: you will need 3 separate handlers or, customize one handler with arguments preset (still 3 function objects).

Chapter 20

860 :: 20.2.1 :: Table 20.2 : In the header for the first column, net_loc should be in Courier Bold Italic.

868 :: 20.2.4 :: Example 20.1 :
      • Adjust line 20 so it is flush with the other lines of code.
      • Change the filename to urlopenAuth.py (see next erratum).

868-869 :: 20.2.4 :: Line-by-Line Explanation :: Lines 24-29 : Change the filename to urlopenAuth.py (see next erratum). The current name (urlopen-auth.py) will not allow the module to be imported since '-' is not a valid Python identifier.

871 :: 20.3 :: Example 20.2 : The code for the __init__() and filename() methods (lines 15-34) are not indented properly... there should be 4 spaces of indentation for these methods.

878 :: 20.5.1 : The final line of code on this page is missing an optional parameter... it should read as: $ python -m CGIHTTPServer [port].

879 :: 20.5.1 : In the final paragraph of this section (above the URL links), cgi-bin is accidentally titlecased twice.

880, 890-892, 897-898 :: 20.5.2, 20.5.5, 20.7.4 : Figures 20-4, 20-9, 20-10, 20-11, 20-14, 20-15 : The captions should be centered so they fit on a single line below each figure.

NEW (May 08)
885 :: 20.5.4 :: Example 20.5 : The if clause (line 49) should be indented at the same level as the else clause (line 51).

896 :: 20.7.3 : In the first complete paragraph at the top of the page, string.split() should be str.split() to indicate usage of the split() method of strings rather than the split() function of the string module.

911 :: 20.9 :: Table 20.7 : In the description for the wsgiref module, "application" should be in plural, e.g., "applications."

913 :: 20.10 :: Exercise 20-3 : Remove the extra comma in the reference to Example 11.4.

914 :: 20.10 : Exercises 20-10 and 20-11 : Exercises 20-7 through 20-10 are related and grouped together; there should be an extra blank line separating Exercise 20-10 and 20-11.


Chapter 21

928 :: 21.2.2 : Methods : Table 21.5 : Each of the arguments of errorhandler() should be in Courier Italic. There should also be some text just able this table which describes the error-handling mechanism further, such as, "An option for database adapter writers to allow for user-defined error handlers is available. Both Connection objects as well as Cursor objects (see next section) allow module authors to define an errorhandler() method for this purpose.

929 :: 21.2.3 :: Table 21.6 : For the description attribute description, both name and type_code at the end should be in Courier Italic.

935-936 :: 21.2.7 :: MySQL : At the bottom of p. 935 through the end of the entire paragraph on the top of the next page, we claim, "... that no database modules are available in the Python standard library...." As we see in the SQLite section on the very next page, beginning with version 2.5, the pysqlite database adapter does come with Python (as the sqlite3 module).

937 :: 21.2.7 :: SQLite : The pysqlite database adapter should not be in Courier.

939-945 :: 21.2.7 :: (Example 21.1) : There is no output for Example 21.1; however, we do provide the output of the equivalent ORM versions (twice) later in the chapter. The output of those applications will be the virtually the same, given the natural variations of the random numbers generated.

940-953 :: 21.2.7-21.3.3 :: Examples 21.1-21.3 : In various places, the font was shrunk so as to not wrap lines. This may look strange in the text. These include the following:
      • Example 21.1: 54, 107-115, 136
      • Example 21.2: 56, 64, 75, 99
      • Example 21.3: 71

941 :: 21.2.7 :: Example 21.1 : Line 55 should be flush with the others in this elif clause.

947 :: 21.3.3 :: Line-by-Line Explanation :: Lines 33-44 : try-except should be in bold.

953 :: 21.3.3 :: Line-by-Line Explanation : In the section for lines 79-80, there should not be a space between the function name and parameters in the getattr(orm, 'drop') call, and further on, self.users should be in mono (Courier) font. Finally, there are too many blank lines above and below the next section (lines 82-84).


Chapter 23

987 :: 23.1.1 : Table 23.1 : Footnote "b" can be worded better: "Some values come back (additionally) quoted although all are returned as part of a single CSV string from the server."

988 :: 23.1.1 :: Example 23.1 : stock.py
Line 20 should be u.close().
(critical patch)

998 :: 23.2.5 :: Example 23.5 : olook.pyw
For running the demo), the outlook() function should be named olook() (to match the name of the module) because that is what the demo expects. Since we are lazy, we just simply create an alias to the original function by inserting a new line 31 which reads: olook = outlook. If you're not going to run it, this change is not necessary.
(minor patch)

1001 :: 23.2.6 :: Example 23.6 : estock.pyw
Line 43 should be u.close(). Also, on line 25, "as" should not be bolded.
(critical patch)


Appendix B

NEW (May 08)
1025 :: Table B.3 : In footnote (b), it refers erroneously to Table 5.2... it should be Table 5.3.

NEW -- Thanks to Raven Erebus (May 08)
1038 :: File Object Methods and Data Attributes : The section title has "Attributes" misspelled... remove the extra "o".


CREDITS

Thanks to the many readers who have provided invaluable feedback and corrections in this section. They include but are not limited to: David Librik, Sebastian Strempel, Loek Engels, Steven Wayne, Viraj Alankar, Johan Neven, Dave Hines, Barrett Shiff, Harold Trammel, Marie-Cécile Baland, Greg Nofi, Mark Ackerman, Tony Tang, Adil Lotia, Satoshi Tanabe, and others.

[Core Python Programming]
[powered by Python]
© 2001-2008 CyberWeb Consulting
corepython (at) yahoo (dot) com