Jeremy Caney (28) [Avatar] Offline
#1
Naomi—

Thank you for putting together the third edition of The Quick Python Book. I've been recommending this to my staff as they're already experienced programmers, but there are a lot of quirks and syntactical shortcuts that are easy to miss if you take a purely reactive approach to learning Python (e.g., just looking up the immediate equivalents for expected features based on other languages).

I realize you are preparing to go to press (congratulations!) so my feedback below may not make it into your final manuscript. Further, as I am reading v08 from December, you may well have caught many of these in the meantime. If not, however, I hope these are useful! I'm not yet finished with the MEAP, so this only covers the first ?18% of the book; if there's time, I'm happy to submit more in the next week or two when I finish the book.

Typos
The following typos are the highest priority, but also the easiest to address:

  • 1.5: “Python has “B=built-in advanced features” should be “Python has built-in advanced features”

  • 2.2.1:Update Shell Profile. command" should be “Update Shell Profile command”, I believe, with “command” in proportional type face

  • 2.6: “Installing Python 3 on Windows systems it’s as simple as” should be “Installing Python 3 on Windows systems is as simple as”

  • 3.1:try-except -else-finally” should be “try-except-else-finally” (note the extraneous space)

  • 3.3.2: “If none of the conditions is true” should be “If none of the conditions are true”

  • 3.3.7: “One benefit of context managers is that the may” should be “One benefit of context managers is that they may”

  • 4.10:bar(“ – Was this meant to be “bar()”? Or is it an intentional typo for the purpose of the exercise?

  • 5.5.7: “Which of the following with raise an exception?” should be “Which of the following will raise an exception?”

  • 5.5.7: “Modify that code to remove the element only in the item” should be “Modify that code to remove the element only if the item”

  • 6.4.2: "You may pass int an optional second argument" should be either "You may pass an int as an optional second argument" or, perhaps, "You may pass in an optional second argument"

  • 6.4.3: There should be a break before "#1 Strips off all gs, os, and rs" to maintain consistent formatting

  • 6.4.6: "What would be a quick way change all punctuation" should be "What would be a quick way to change all punctuation"

  • 6.5: "Basically, I wanted you to be aware" should be "Basically, I want you to be aware" for consistent tense

  • 6.8: The pi = 3.1415 assignment should be in the following code block, along side the rest of the pi example

  • 6.9: There is missing code at the end of Lab 6; it starts off with with open(" but doesn't provide the code for reading and writing files

  • 7.1: "use of dictionaries and lists often appears alike" should read "use of dictionaries and lists often appear alike" ("appears" should be singular)

  • 7.1: "a person can be stored indexed by that person's last name"—should be either "stored" or "indexed" but not "stored indexed"

  • 7.1.1: "…ask the user for one on the names" should be "…ask the user for one of the names" ("of" not "on")

  • 7.2: x.get('y',None) should be x.get('y', None) for consistency (missing space after comma)

  • 8.3.1: "sequences of  integers" should be "sequences of integers" (there's an extra space before "integers")

  • 8.3.5: The variables in the footnotes (i.e., x, y, and z) should be monospaced for consistency

  • 8.4.1: "if divided by 2, use % 2 to for this" should be "if divided by 2; use % 2 for this"

  • 8.6.2: "if an expressing with and has even one" should be "if an expression with and has even one"

  • 8.6.2: "The converse is true for or" should be "The converse is true for or" (i.e., "or" should be monospaced)

  • 8.6.2: The code statements in the Quick Check should be monospaced (e.g., "1 and 0, 1 > 0 or []" )

  • 8.8: The trailing period after "if-elif-else" should not be monospaced (super nit-picky, I know!)

  • 9.1: The last footnote (#3) should use monospaced type for the x (it's currently italicized, which looks fine but is inconsistent)

  • 9.2.4: There is an extraneous space between "by" and "the" in "followed by  the indefinite positional argument"

  • 9.7: The reference to yield from should be monospaced in the body of the yield vs. yield from callout box (i.e., "yield from behaves the same as yield")

  • 10.2: The constant pi should be uppercase (i.e., PI) as per the Python style guidelines discussed in Section 4.10 and summarized in Table 4.1

  • 10.2: "Internally to Python" should be "Internal to Python…"

  • 10.3: "…don't begin with an underscore, and…" should be "don't begin with an underscore—and…" (note em-dash) to close the interjection about private names

  • 10.4.1: I assume the trailing period in PYTHONPATH. is a typo, and should be removed

  • 10.7: There is an extraneous instance of >>> at the end of the first code block

  • 10.7: In the Quick Check, references to "width" should be monospaced (e.g., "Consider a variable width…")

  • 10.7: In the Quick Check, "with the module itself" should read "within the module itself"

  • 11.1.2: The reference to sys.argv in the final sentence should be monospaced

  • 11.1.3: "writes to its standard output whatever it read" should be "writes to its standard output whatever is read"
    (or, perhaps, "whatever it reads")

  • 11.1.3: The references to print, sys.stdin, and sys.stdout should all be monospaced

  • 11.1.4: In the footnote for #2, it should be '--file', not '—file' (i.e., it should be two hyphens, not an em-dash)

  • 11.1.4: The reference to "verbose" should be monospace (i.e., "also adds the ability to turn off the verbose
    option")

  • 11.1.5: sys.argv should be monospace

  • 11.1.5: "fileinput.input also has an inline option" should be fileinput.input also has an inplace option" to reference the specific option by name, thus making it easier for the reader to find it in the documentation

  • 11.1.5: In the Quick Check, "getting" is unnecessary and "commandline" should have a space: "Match up the following ways of interacting with the command line"

  • 11.1.5: In the Quick Check, "arguments" is misspelled in "Multiple argurments and options"

  • 11.3: The reference to "section 11.7, 'Distributing Python applications'" is incorrect; it should be "section 11.6, 'Distributing Python applications'"

  • 11.4.1: The reference to python in the body of the Python doesn't run? callout box should be monospaced

  • 11.5: #I is missing from Listing 1.10, even though it is referenced in the annotations

  • 11.5: "create a simplistic user interface" should be "create a simple user interface" (or even "a very simple user interface"); "simplistic" implies oversimplified

  • 11.5: "to use the input" should be "to use the input function"

  • 11.5: "it can become an self-contained executable" should be "it can become a self-contained executable"

  • 11.5: __main__.py should be consistently monospaced (it isn't in the third paragraph)

  • 11.6.4: "In general, however this is still and difficult and complex path… unless you a strong need and the time and resources to make it work" should be "In general, however, this is still a difficult and complex path… unless you have a strong need, the time, and the resources to make it work"

  • 11.6.4: In the Lab, there is an extra space before "Now that we have more tools…"

  • 11.6.4: In the Lab, there is a missing period after "shown" in the last sentence of the first paragraph

  • 11.6.4: References to man and -L in the last paragraph of the Lab should be monospaced

  • 11.7: I believe "The UNIX or Mac OS commandlines" should be "The UNIX, or Mac OS, or Windows command lines" (should include Windows, and is missing a space in "command lines")

  • 11.7: "Now that have an of the ways" should read "Now that you have an understanding of the ways"

  • 11.7: There's an orphaned sentence at the end of this section; it simply reads "Understanding."

  • 12.1: There should be a comma after "Since Python 3.5"

  • 12.2.1: In previous chapters, file paths were treated as monospaced; they should be treated the same here, for consistency

  • 12.2.4: "The arguments to os.path.join need not be single directory or filename" should be "The arguments to os.path.join need not be a single directory or filename"

  • 12.2.4: "Anything else can be considered as an invalid pathname" can simply be "Anything else can be considered an invalid pathname"

  • 12.2.4: There an extraneous comma after "Similarly, os.path.expandvars does the same for environment variables.,"

  • 12.2.5: There are two code blocks in this section that need to have the code block styling to them; they are currently being displayed as proportional-width body text

  • 12.2.5: There is an extraneous end-quote after "The same result can be achieved by the slash operator"; this should be a colon, instead

  • 12.2.5: "the suffix property" should be "the suffix property" (note monospace font)

  • 12.2.6: Instead of "take a path to a file" it should be "make a path to a file" (though I suppose they both work in a way)

  • 12.3.1: os.path and with should be monospaced

  • 12.4.1: "in Windows environment" should be "in Windows environments"

  • 12.4.1: WindowsPath and PosixPath should both be monospaced as class names

  • 12.6: In Table 12.1, "old_path_obj.rename" should be old_path_obj.rename(new_path)" (with parenthesis) for consistency with other methods

  • 12.6: In Table 12.2, under the section for "Path.mkdir([parents=True])", the description should read "Creates a directory; if parents is True also creates needed parent directories" (note monospaced references, and plural for parents and directories)
    [list]13.1: The reference to with should be monospace ("Note also that this example uses the with keyword…")

  • 13.3: The terms "reads or writes" should not be monospaced, as they don't refer to code identifiers

  • 13.4: The references to newline should be monospace, since it refers to a code identifier

  • 13.5: "writing replaces any existing comments" should be "writing replaces any existing content"

  • 13.6: The reference to sts.stdout.write in annotation #A should be monospaced

  • 13.6: There should be a space after f in fourth code block ("f = open('outfile.txt', 'w')")

  • 13.6: In the final paragraph, all inline references to functions end with parenthesis (e.g., print_file()); personally, I prefer this, but it's inconsistent with other references to functions in the book, which exclude the parenthesis

  • 13.7: The annotations should be "Reads in a single record" and "Unpacks the record into a tuple"

  • 13.7: In the last paragraph, "C short integer" should either be "a C short integer" or "C short integers"

  • 13.8: In the third code block, the files modes should include the b binary flag (i.e., wb and rb respectively)

  • 13.8.1: "While in might make some sense…" should be "While it might make some sense…"

  • 13.8.1: In the Quick Check, "A0" should be "A)"

  • 13.8.1: In the Quick Check, "from one on run to the next" should be "From one run to the next"

  • 13.9: In the Lab, there are two spaces before "In addition…"

  • 13.9: In the Lab, wc should be monospaced

  • 13.10: "the struct module does give you" should simply be "the struct module gives you"

  • 13.10: The final sentence currently ends with a comma ("Python data structures,"); it should end in a period

  • 14.1.1: "don't have the time or the energy put in this" should be "don't have the time or the energy to put into this"

  • 14.2: In the (very useful) exception tree reference, there are a number of exceptions that are ambiguously indented by one space, making it unclear if that's a typo or another level of indentation (e.g., OverflowError, VMSError, RuntimeWarning, &c.); for clarity, I'd ensure all indentations are four spaces, and remove any inadvertent single-space indentations

  • 14.2.3: "If the line except exception_type, var: matches…", the code should read, "except exception_type as var:"

  • 14.2.3: "matches some thrown expression exc" should be "matches some thrown exception exc"

  • 14.2.3: In Try This, the ZeroDivisionError reference should be monospaced

  • 14.2.4: In the fifth code block, there is an unnecessary line break after error.args[0],

  • 14.2.4: In the Quick Check, "MyError" and "Exception" should both be monospaced

  • 14.2.8: There's an extraneous comma in the code block after function; it should read "return function(x,
    y, spreadsheet)
    " I believe

  • 14.2.9: In Quick Check and Try This, the terms x, None, KeyError, and ValueToLarge should all be monospaced

  • 14.3: In Quick Check, the four instances of the keyword with should be monospaced

  • 14.3: In the Lab, the first line uses a novel blue text style, unique to this section (so far), which reads like a hyperlink, but isn't active—I assume this is an error

  • 14.4: "Using try, except…" should be "By using try, except…"

  • 15.1.1: __init__ should be monospaced

  • 15.2: The header for the Try This callout is light blue, which looks nice, but is inconsistent with other callout headers across the book

  • 15.4: "accessed" in the first sentence should be "accessible"

  • 15.5.1: all_circles should be monospaced

  • 15.5.2: The annotations (#A, #3) should be on the same line as the code, for consistency

  • 15.6: In the annotations, Square, Shape, __init__, and Circle should all be monospaced

  • 15.6: The text suggests, "There are (generally) two requirements in using an inherited class in Python, both of which you can see in the bolded code in the Circle and Square classes", and yet only the first requirement (the actual inheritance syntax) is bold; the calls to super().__init__(x, y) are not bold, but should be

  • 15.8: __init__, self, move], Shape, Circle, pi, all_circles, super(), total_area, cls and circle_area should all be monospaced in the annotations and text

  • 15.8: The "for icircle in cls.all_circles:" block in the second code block should be monospaced

  • 15.8: "In __init__ method instance adds itself…" should be "The __init__ method instance adds itself…"

  • 15.8: "takes the class itself (cls) as parameter" should be "takes the class itself (cls) as a parameter"

  • 15.8: "paramettrs" should be "parameters"

  • 15.9: The __y in the annotation should be monospaced

  • 15.9: In Try This, the reference to Rectangle should be monospaced

  • 15.10: The annotations (#1, #2) should be on the same lines as the code, for consistency

  • 15.10: In Try This, "getter" should be "getters"

  • 15.11: In Figure 15.2, the "Private Instance" box should read "Private instance variables"

  • 15.11: In Listing 15.3, there should be a space after the first equals sign ("mv = "module variable: mv")

  • 15.11: In Listing 15.3, the description for __pcv should be "private class variable", not "class private variable" for consistency

  • 15.11: In Listing 15.3, the description for self.iv should be self.iv not self.xi

  • 15.11: In Listing 15.3, the print() statements for headers/labels should have an extra line break before them, not after them, so they're associated with the subsequent content

  • 15.11: In Listing 15.3, there are two extra line breaks within the print() statement immediately after annotation #D

  • 15.11: In Listing 15.3, there should be a space before "dir(self) at annotation #E

  • 15.11: In Listing 15.3, the annotations should be lined up; they are indented less after #I

  • 15.11: There is no comma needed after mf in "…and the module function mf, (which…"

  • 15.13: After the numbered list, the sentence starting with "Class F does contain a method f…" should actually be item number 5 in the list

  • 15.13: In the Lab, HTML elements (e.g., <html>, <body>, and <p>) should be monospaced

  • 15.13: In the Lab, there should be a space between "(optional)" and "text"

  • 15.13: In the Lab, __str__() should be monospaced

  • 15.14: "The self parameter refers to the current instance of the class is passed as the first parameter…" should read "The self parameter refers to the current instance of the class and is passed as the first parameter…"

  • 16.1: The words "of the" should be removed in the third sentence: "A RE is defined by a string in which certain of the characters (the so-called metacharacters) can have a special meaning…"

  • 16.1: In the second-to-last sentence, "than" should be "then": "If the regular expression is found in the string, then Python returns…"

  • 16.2: "in the online documentation" should be "can be found in the online documentation"; otherwise it doesn't make sense: "A complete list of special characters available in Python regular expressions… in the online documentation…"

  • 16.4: The also in "This also means an optional group of 3 digits plus a hyphen…" is unnecessary;
    in context, it's explaining the previous point, not adding another point to it, as implied by "also"

  • 16.4: The abbreviated (\d{3})-)?\d{3}-\d{4} format is introduced in the sixth code block, but all subsequent code blocks use the more verbose (\d\d\d-)?\d\d\d-\d\d\d\d format; they should all use the abbreviated format

  • 16.5: I like the idea of indexing the labs (e.g., "Lab 16: Phone Number Normalizer"); that said, this hasn't been consistently done—it'd be worth ensuring all of the labs are indexed, or that none of them are

  • 16.5: In the Lab, the first sentence should begin with "Phone numbers in the USA and Canada consist of 10 digits", otherwise the sentence doesn't make sense

  • 16.5: In the Lab, "formats" should be "the formats": "create a phone number normalizer that takes any of the formats mentioned above…"

  • 16.5: In the Lab, "thig" should be "this": "Use this information to validate the input…"

  • 16.5: In the Lab, ValueError should be monospaced

  • 16.6: match should monospaced since it references the object type

  • 17.1: int and list should be monospaced in the second paragraph

  • 17.3: Before the seventh code block, the variable should be __name__ not __nam___

  • 17.3: In the final code block, annotation #2 should be aligned with the rest of the annotations

  • 17.3: In the final code block, "The issubclass function…" should be taken out of the code block and made body text, since it's neither code nor output (also, issubclass should be normal size; it's currently larger)

  • 17.4: The final paragraph references Chapter 20, which is on File Wrangling; is this correct?

  • 17.7: The annotation #D is not properly aligned with other annotations

  • 17.8: Toward the end of the section, "the first four items in x" should be "the first five items in x; it is unpacking a-e (even if it's only printing a-d on the next line)

  • 17.8: In the last sentence, append should be monospace since it refers to the method

  • 18.2: In Figure 18.1, I believe the dotted boxes should be labeled "constants.py" (for the filename) and not "constants.pi" (for the specific constant inside of them)

  • 18.3.4: The reference to "versions" in the second paragraph should be "version" since it refers to the singular variable name

  • 18.3.4: There should be a space between "__name__" and "property" in the last paragraph

  • 18.5: Under the Lab, the last sentence should start with "Then write a simple main function…" not "The write a simple main function…"


  • Readability Suggestions
    The following are more subjective, and aren't critical for publication, but may make certain sections flow a bit better, and thus improve readability. These are the sentences I found myself tripping over and, thus, having to read twice.

  • 1.3.1: “Languages like C, Java, and Perl have even larger collections of libraries available, in some cases offering a solution where Python has none or a choice of several options where Python might have only one”; I suggest adding an em-dash, or similar, after "where Python has none" to break up the two parts of the sentence

  • 2.1: “as administrator” would read better as “as an administrator”

  • 3.2.2: Consider aligning the footnote references (#1, #2, #3, #4) for readability

  • 3.4: “in a directory or directory subtree and import and hierarchically refer” might read easier as “in a directory or directory subtree and import in order to hierarchically refer”

  • 4.3: “a letter or underscore” might read better as “a letter or an underscore”

  • 4.4: “Even though all the values are integers” might read better as “Even thought all of the values are integers”

  • 4.10: The sentence on PEP gets a bit wordy; consider breaking it up into two sentences (e.g., “This is summarized in the appendix”)

  • 5: “Most of this chapter is devoted to lists” — since lists were already discussed, and are being returned to, consider adding a “however” to this sentence so that transition back to lists is acknowledged

  • 5.4.2: Consider, “To address this, Python also has the built-in function sorted()” so it’s clear this addresses the issue raised in the previous sentence

  • 5.5.3: The “(which in this context is called the list multiplication operator)” aside is useful, but makes for a wordy sentence; consider rewording

  • 5.5.3: Consider “joins all of the copies” instead of “joins all the copies”

  • 5.6: “This is the result of the combination of the way variables” is a bit wordy; consider “of a combination in the way”, to avoid the repetition of "of the"

  • 6.5: Consider "try repr around another built-in complex object" to acknowledge that this is separate from the complex list object just discussed

  • 6.6.3: The opening sentence is wordy on account of four instances of "format(ting)". Consider e.g., "Format specifiers let you define the formatting results with even more power and control than the sequences used by the older style of string formatting"

  • 6.7.2: I tripped over the wording at the end of the first paragraph. Consider e.g., "If you'd prefer, you can skip ahead to the next chapter, 'Dictionaries', and then return to this section after; alternatively, you may read straight through, trusting to the examples to make the functionality clear"

  • 6.7.2: To avoid the duplicate "print print" consider "calls to print output each value on a separate line"

  • 6.8: To avoid the duplicate "is a way" consider e.g. "This allows the developer to include"

  • 7.2: "that is, lists or other dictionaries" makes more sense as "for instance, lists or other dictionaries", since there are other modifiable objects, and especially in custom applications and third-party libraries

  • 7.4: "…except that when you have them, you can't modify them" might read easier as simply "…except you can't modify them"

  • 7.5: "as shown at right"—in the e-book, at least, the image shows below, not to the right

  • 8.7: The style for listings—first appearing in 8.7—displays as black on dark blue in my e-reader (Marvin 3 on iOS) making it difficult to read

  • 8.7: Consider aligning the footnotes (e.g., "#D") in the code sample with one another where practical

  • 9.1: I'd suggest "follow this with a blank second line, and end with" be reworded as "followed by a blank second line, and ending with"

  • 9.1: I found "shows the value" confusing here, since returning a value doesn't innately show the value (e.g., if it's being assigned to a variable); I'd suggest "This line returns the value to the code calling the function"

  • 9.2.2: Consider changing "in the final invocation of it are named" to "in the final invocation are named"; in context, this reads easier

  • 9.3: I was initially confused by the diagrams until I saw the code that they illustrate; I'd recommend moving the code to the top so the figures have context

  • 9.7: I found the "When there are no more iterations…" sentence a mouthful; I'd suggest something like: "The generator will stop returning values when there are no more iterations, or it encounters either an empty return statement or the end of the function"

  • 9.7: I'd change "Starting with Python 3.3 the new key word…" to "Starting with Python 3.3, a new keyword…"

  • 9.8: "Functions can be passed as arguments" might be clearer as "Functions can also be passed as arguments", since it's extending the use case already discussed (i.e., assigning functions to variables)

  • 10.3: I'd remove the preceding "But" in "But some modules…" since it isn't really contradicting the previous statement

  • 10.4: I believe the more standard turn-of-phrase would be "in the search path" not "on the search path"; if so, it should read "look at the search path and the modules in it"

  • 10.4.1: The final instance of "code" can be removed from the segment ending with "hard-codes directory locations into your program code" in order to reduce occurrences of "code" in the sentence

  • 10.4.1: Consider italicizing references to the documentation to further distinguish them as titles; e.g., "…in the Python documentation in the Python Setup and Usage section under Command line and environment"

  • 10.4.1: "The last of these mechanisms" and simply be "This mechanism" since the entire paragraph is already about the last mechanism (i.e., using the sys.path approach)

  • 10.4.1: Consider changing "Assume your sys.prefix is c:\program files\python, and place the file in listing 10.2 in that directory" to "Assuming your sys.prefix is c:\program files\python, place the file from listing 10.2 in that directory"

  • 10.4.1: Consider merging the "Note that the mymodules directory" sentence with the next via a semicolon since they're so closely related; e.g., "…overwritten with a new installation; the modules directory is safer"

  • 10.5: Consider changing "this manner so that people" to "this manner, thus allowing people" to better distinguish and emphasize the purpose of the pattern (nit-picky!)

  • 10.7: To better differentiate ideas, add a comma before "as an optimization", so that it reads: "It was necessary in this case due to the fact that in modules, as an optimization, the whole…"

  • 10.7: To clarify "current settings" consider something like "The dir function doesn't give the current values associated with each identifier"

  • 11: "when you need to process large numbers of files" reads easier as "when you need to process a large number of files"

  • 11.4.1: Consider "in the Using Python on Windows section of Python Setup and Usage in the online Python documentation for more specific instructions" instead of the wordier "in the Python Setup and Usage section of the online Python documentation in the Using Python on Windows section for more specific instructions"

  • 11.5: Consider rewording "rather than having it as a command-line option and keeping the screen up to display the output by…" as "rather than having it as a command-line option. This can be achieved by…"

  • 11.5: Instead of "to the beginning of the archive" I'd explicitly state "to the beginning of the __main__.py file so it's clear what is being referred to

  • 11.5: Typically, "she-bang" is not hyphenated; when it is, it is usually spelled "sha-bang" (though, personally, I've always been partial to "hashbang", acknowledging that's a stylistic preference)

  • 11.6.4: "with an application" is unnecessary in the final paragraph; it is easier to read without it

  • 11.6.4: "Feel free to try to" and simply be "Try to" for simplicity

  • 12.1: "would be ideal" might be easier to read as simply "necessary"

  • 12.1: Instead of "a more object oriented and more unified way", consider "a more object-oriented and unified way"

  • 12.1: "would be done using pathlib" might be easier to read as "can be done using pathlib"

  • 12.2: "…to separate file or directory names" can be removed since it is effectively covered by the context of the previous "to separate sequential file or directory names"

  • 12.2.2: Consider changing "but will change as you issue commands that change the value of the current working directory" to "but will change as you issue commands that alter the value of the current working directory"
  • to avoid the repetition of "chance"
  • 12.2.4: Consider joining the last two sentences of the second paragraph with a semicolon since they're closely related: "Note that importing os is sufficient to bring in the os.path submodule as well; there's no need for an explicit import os.path statement"

  • 12.2.4: I'd say, "First, let's start with Python under Windows" since you're then going to switch to UNIX; this isn't about "starting Python" but "starting… under Windows", which the "with" helps clarify

  • 12.2.4: "MS Windows" should just be "Windows" for consistency (everywhere else it's referred to as simply "Windows")

  • 12.3: Consider merging the two sentences regarding specialized queries: "os.path.islink and os.path.ismount are useful in the context of Linux and other UNIX operating systems; they return True if, respectively, a path indicates a file that's a link or a mount point" (removed "…that provide file links and mount points" as it seemed implicit in context, and made the sentence wordier)

  • 12.3.1: is_socket wasn't discussed in the previous section, as implied here

  • 12.3.1: Consider rewording "…and it is recommended to use one" to "…and it is recommended to ensure resources are properly disposed of", which both reads better, while also reinforcing the purpose of the context manager

  • 12.5: Consider using the (implied) variable dirs, to tie into the next code block, instead of names, which has no association, and is a bit ambiguous

  • 12.5: To avoid ambiguity, consider changing "It also has the already-mentioned rmtree function…" to "shutil also has the already-mentioned rmtree function…" since the previous sentence was about copytree and not shutil specifically

  • 13: The first sentence might make more sense as the first sentence of Section 13.1; as a stand-alone paragraph it feels a bit anemic

  • 13.1: Instead of "the next call to readline would return the second line, and so on", consider "the next call to readline would return the second line, if it exists, and so on" to reinforce the limits of the iterator

  • 13.2: Consider moving the sentence "Using a context manager…" to after the first code block, replacing "or this:",
    in order to separate the concept of closing the files from the two techniques for closing them

  • 13.4: "If the file has been opened in binary mode, the newline parameter isn't needed"—but it then goes on to show the newline parameter; the code block doesn't match the description

  • 13.6: The sentence "If you're using IDLE…" would make more sense with the subsequent paragraph

  • 13.6: The sentence "If you're using IDLE…" might be combined with the following sentence via a semicolon: "…sys.__stdout__ won't work as indicated; you have to use the interpreter's mode directly"

  • 13.6: Might interject "assuming capture_output hasn't been executed" into the sentence starting with "Also,
    print_file() prints this file to the standard output…" to clarify the state of the functions

  • 13.7: The following two sentences would work well combined by a semicolon since they're so closely related: "Note that there is no checking for file consistency; if the last record is an of size, the struct.unpack function raises an error"

  • 14: To reduce wordiness and repetition, consider removing "include exceptions" in the second paragraph; this is implied by "which do"

  • 14.1.2: To reduce wordiness, consider just saying "or explicitly raised by your own code" instead of "or can be explicitly raised by your own code"

  • 14.1.2: I'd recommend grouping the sentences discussing the previous example together, to consolidate discussion of that code; e.g., "In the previous example, all exceptions are raised by the disk-writing functions (not seen in the code), which would throw an exception if the disk were to run out of space. In addition, exceptions can be raised by any other functions or explicitly raised by your own code"

  • 14.1.2: The text "other exception handlers" in the last sentence can safely be removed; it is implicit

  • 14.2: Consider adding: "If you aren't familiar with OOP, though, you don't need to learn OO techniques in order to use exceptions"

  • 14.2: I'd recommend moving the definition of the raise statement to its first mention, which will also reduce the wordiness of the second sentence: "It's generated automatically by Python functions with a raise statement—which,
    as the name implies, raises an exception
    . After the exception is generated, the [rr]raise[/tt] statement causes execution of the Python program…"

  • 14.2: In the Easier to ask forgiveness than permission callout box, "that common in" is unnecessary and can safely be removed

  • 14.2: In the Easier to ask forgiveness than permission callout box, "LYBL" should be "LBYL"—"LYBL" stands for "live your best life", which is also good advice, but less relevant here smilie

  • 14.2.2: The words "the line containing" can safely be removed

  • 14.2.3: The words "do something else" (and the comma after words) can be removed
    [list]14.2.3: The "the" prior to "else keywords" can be removed (since "the" is implied by the beginning of the list)

  • 14.2.3: "to be caught by the try statement" can be removed; it is implicit

  • 14.2.3: "Since there is a finally statement finally_body is executed" would read better as "Since there is a finally statement, the finally_body is executed"

  • 14.2.3: "the thrown exception is assigned to the variable named after the associated exception type" could probably just read "the thrown exception is assigned to the variable" to reduce wordiness, while not losing much clarity

  • 14.2.3: Consider "the exception code body associated with the matching exception is executed" tp reduce the occurrences of "exception" in the sentence

  • 14.2.3: I'd prefix "If the line exception exception_type, var: matches…" with "So, for example…" to clarify that it is providing a concrete illustration of the previous sentence, not making a new point

  • 14.2.4: Consider adding an "e.g." prior to "WeatherLibraryException" to further illustrate that it's an example

  • 14.2.6: Consider "…and what that means" instead of "…and on what it means"

  • 14.2.7: Consider merging the last two sentences of the second paragraph with a semicolon: "It would be easy to develop the program first and to add error-handling code later; in fact, that's often what is done, although this isn't the optimal ordering of events"

  • 14.2.7: Consider merging the last two sentences of the subsection with a semicolon: "…raising your own DiskFull exceptions as necessary; I wouldn't recommend this latter option, but it's nice to know the possibility exists…"

  • 14.4: Consider using em-dashes: "…and by selecting—and even creating—the types of exceptions caught…"

  • 15.1: Consider merging with a semicolon: "No assignments or function definitions are required; the body can just be a single pass statement." (I also flipped the order of "just" and "be")

  • 15.1: "CapCase" is better known, I believe, as either "PascalCase" or "upper camel case"; either of those might be a preferable term here

  • 15.6: "that looks like this" is an awkward turn of phrase; consider simply, "this looks like"

  • 15.9: Consider combining the last two sentences of the first paragraph with a semicolon: "…they explicitly indicate what is used only internally in a class; anything else is the class's interface"

  • 15.9: The "private" at the end of the second paragraph can be removed; it is contextually implicit

  • 15.10: The sentence "Suppose you want a value before you put it into an instance variable" reads as incomplete;
    was it intended to be "Suppose you want to validate a value before you put it into an instance variable"?

  • 15.11: In the globals(), locals(), and dir() output, it'd be useful to either bold the relevant objects,
    or otherwise introduce a simple helper function that removes objects of pattern __%__, to help draw attention to the relevant pieces

  • 15.13: Consider adding a comma after "in left-to-right order"; without it, the sentence is a lot to parse

  • 15.13: "as in" is unnecessary in the aside, "—for example, as in mixin or addin classes—"

  • 16.1: To avoid the repetition of "which" consider replacing "which enables" with "enabling" in the third sentence:
    "A RE is defined by a string in which certain of the characters… can have a special meaning, enabling a single RE to match many different specific strings."

  • 16.2: The words "in regular expressions" can be safely removed from the sentence; it is implicit in context: "Quite a few special characters are available in Python regular expressions, and describing all of the subtleties of using them in regular expressions is beyond the scope of this book"

  • 16.3: Consider replacing "…that doesn't apply the normal Python rules to special characters, and strings defined this way are called raw strings" with "…that doesn't apply the normal Python rules to special characters; strings defined this way are called raw strings"; this reads easier

  • 16.3.1: I recommend interjecting "by Python" in "sequences aren't interpreted by Python as tabs or newlines…" to make it clear that this is referring to the Python interpreter, and not the regular expressions interpreter

  • 16.4: In the first sentence, "…perform a simple pattern-based parsing on text" should probably be "…perform a simple pattern-based parsing of text" (though an argument could be made for either)

  • 16.4: Consider using the more specific term "element" in place of "thing" in "which says that the element coming immediately before the ? is optional"

  • 16.5: In the second to last sentence, the reference to sub should be int_match_to_float, as that's what is actually returning the new string; I'd clarify this as "int_match_to_float returns the new string and sub incorporates it as a substring…"

  • 16.5: In the Try This you refer to "the checkpoint above"; consider saying "the previous Try This" for clarity (since they're not labeled as "checkpoints")

  • 16.6: You can safely remove "in the main arguments string" from the second bullet point; it is clear in context, and removing it will make the sentence more readable

  • 17.3: You can probably get away with either, but I think the first sentence would be less ambiguous as "type of objects" (though it's hard to say; this all stems from the definition of "type" being overloaded)

  • 17.5: Consider prefacing the sentence "Special method attributes can be used to define classes whose objects behave in a fashion that's syntactically and semantically equivalent to lists or dictionaries" with "Among other things…"; this reinforces that this is just an example of what special method attributes can do, and not their primary purpose

  • 17.6: Evaluate if there's a way to remove the repetition of "wanted to" in the last paragraph; it makes the sentence a bit wordy

  • 17.7.1: "and inside" isn't necessary in the first paragraph after the bullet list, and makes the sentence a bit of a mouthful

  • 17.8: You can probably get away with either, but "The accesses of elements of x" might read better as "The accessing of elements of x…"

  • 17.9.1: The second "that" in the last paragraph can be removed for readability: "Note that all that we need to do…"

  • 18.3.2 Consider removing the second "can" in the last sentence: "In use, packages can look a lot like modules;
    they can provide access to objects defined within them via attributes"

  • 18.3.4 To disambiguate from "files in other packages", I'd change "other package files" to explicitly state "other files in the package"


  • Content Suggestions
    The following relate to the content, and are mostly low priorities, if not entirely matters of preference.

  • 2.1: “python-3.6.1.exe” might be updated to “python-3.6.4.exe” based on the latest release (acknowledging this will quickly become outdated regardless).

  • 4.1: It might be worth noting here that the indentation structure is arbitrary and can be determined on a per block basis; the only requirement is that it be consistent per block level. That said, establishing a consistent number of spaces per level of indentation is obviously a best practice.

  • 4.3: I’d note that semi-colons can be used to separate multiple statements on a single line. (Obviously, this means they can also be used as line endings in Python—though that would be both unnecessary and stylistically odd.

  • 4:3: There’s a section at the end of 4.3 with some discussion on exceptions. That makes sense in context, but I’d recommend providing a reference to Chapter 14 for additional details.

  • 4.4: “rules of arithmetic precedence”, while correct, might include “(i.e., orders of operation)” for searchability and indexing.

  • 4.6.5: “The important thing to keep in mind is that by importing the cmath module, you can do almost anything you can do with other numbers” – I’m not following the meaning of this. Was it meant to mean “other number modules” (e.g., math)?

  • 5.5.7: I’d consider it useful to include .extend() in Table 5.1.

  • 6.3.3: “We talked before about the different between evaluating a Python expression interactively and printing the result of the same expression using the print function” – I don’t actually believe this was previously addressed, though I might have missed something?

  • 6.5: "repr returns a string representation of a Python object from which the original object can be rebuilt" — this is true for data structures, but isn't true for e.g. functions, as noted previously. This may merit clarification.

  • 7: It may be useful to also relate dictionaries to property bags or key value pairs, and especially since readers may be familiar with these constructs from e.g. NoSQL databases.

  • 7.1.1: "Write the code to ask the user for 3 names and 3 ages" might be a bit of a challenge for readers that haven't read about collecting user input yet. I'd suggest providing an introductory code sample, similar to previous code samples for opening a file.

  • 7.2: It may be valuable to explain why "This method isn't used nearly as often as keys. E.g., "If you were primarily interested in non-keyed access to values, you'd likely just use a list."

  • 7.2: It may be useful to provide an example of how update() might be used. For instance, I often see update() used to merge default values with user preferences when configuring a new instance of a class.

  • 7.2: In Table 7.1, consider specifying "Makes a shallow copy of a dictionary" instead of simply "Makes a copy of a dictionary.

  • 7.4: The first sentence notes that the previous examples used "strings as keys", but the examples covered both strings and integers; this may be worth clarifying. That said, the previous example[/u] (singular) [i]did use strings exclusively.

  • 8.4.1: I am unclear what "special development" means in the first sentence. Perhaps "a special use case" or "a special application"?

  • 8.4.1: It might be useful to compare the idea of a generator back to the previously discussed range(); e.g., "This is similar to range(), except it gives the developer more flexibility to define the sequence based on their own expression and dataset."

  • 9.7: Generators can be confusing when they're first introduced. I'd suggest noting that the processing of the function is effectively paused after the yield statement, thus yielding control back to the calling code; the processing of the function is then resumed the next time it is called. That differs from a normal function that finishes executing before returning a value or control back to the calling code.

  • 9.8: For developers from other programming languages (as this book is targeting) the concept of a decorator can be really confusing since it doesn't map exactly to the Decorator Pattern described in the Gang of Four's Design Patterns: Elements of Reusable Object-Oriented Software. I recommend providing a callout or short paragraph differentiating the two, as done in the Python documentation.

  • 10.4.1: Could you clarify what "site-specific code" is? I'm unfamiliar with this term. I assume it means local to the machine or device?

  • 10.4.1: The c:\My Documents\ folder no longer exists in (native) Windows 10 installations; it is now in the c:\Users\{User}\My Documents folder

  • 10.7: In the Lab, consider adding a note "We will be discussing how to run modules as a program in the next chapter" since e.g., __main__ hasn't been introduced yet

  • 11.1.1 (and elsewhere): For most users, the path to the user's directory will be c:\Users\{user}\ not c:\Documents and Settings\{User}. This was changed in Windows 7 (though machines that have been upgraded to Windows 10 from Windows XP may still have the legacy path).

  • 11.2: In closing, consider explicitly highlighting that the first argument in the sys.argv list is the name of the script itself and not the arguments to the script; i.e., it is providing the arguments to the Python executable. Depending on the context, this may need to be accounted for.

  • 11.1.4: It took me a couple of reads to understand what was going on with action="store_false", dest="verbose", and default="True" in the annotations. This was especially confusing since it says "which is True by default (action="store_false"). I'd recommend rewording these two paragraphs to explain how action="store_false" works, and how that interacts with default="True".

  • 11.1.4: I'm not sure if it's necessary, but the -x/--xray
  • option is never discussed in the annotations, despite it otherwise walking through every other line.
  • 11.5: May want to discuss what [tt]nargs='*' does in the annotations.

  • 11.5: When discussing the option of creating "a separate file with just the portion of the main function that handles the argument", it would be valuable to discuss the benefits of this approach (which I assume is simply to keep the module and the script separate).

  • 11.5: Also related to the above, are there any proposed or recommended naming conventions for distinguishing between a module and a script of the same purpose? If so, that would be useful to include here.

  • 11.6: While instructions on creating wheels are outside the scope of the chapter, it would be useful to provide a bit more detail on what wheels are and why they're useful (e.g., for tying into Python's package management infrastructure).

  • 11.7: Wheels aren't specific to Windows, right? If not, they might be better handled as their own bullet, since their exclusive mention in the Windows bullet point makes them seem like a feature of Windows distributions.

  • 12: Overall, I found Chapter 12 a bit confusing due to the jumping back-and-forth between os and pathlib. Since not all aspects of os were covered in the pathlib sections, I found myself uncertain whether os was still needed if pathlib was being used, and whether all of the best practices for os carried forward as well. Ideally, this would be clearer if the chapter was primarily written from the perspective of pathlib, with references to best practices and os when appropriate, and then included ancillary sections for legacy support using exclusively os. That would probably be a pretty involved refactoring, however, and may not be worth the effort.

  • 12.2.3: I recommend appending to the last sentence, "…as discussed in 12.2.5, 'Manipulating pathnames with pathlib'" so there's a reference for how to "work with a new folder by creating a new path object"

  • 12.2.6: Consider "On Windows 10, it's set to win32—even if the machine is running the 64-bit version of the operating system" (I assume most Windows developers will know this, but it might be useful to point out)

  • 12.3: In the paragraph regarding os.path.islink consider clarifying that islink does work on Windows, but only with true symbolic links (e.g., those creates using the mklink command).

  • 12.4: The text "The difference between them is that os.mkdir doesn't create any necessary intermediate directories, but os.makedirs does:" suggests that the following code block will illustrate this difference, but it doesn't; consider adding a nested directory to the os.makedirs call to clarify the functionality.

  • 12.5: While this is inferred, I'd recommend clarifying that dirs.remove(".git") only removes the .git directory (in this example) from dirs list, and doesn't remove it from the file system; this also helps clarify the previous statement that the "list of subdirectories may be modified (using any of the list-modification operators or methods) before its items are used for the next level of recursion".

  • 13.2: This sections suggests that an advantage of the for approach is that "lines are read into memory as needed"; isn't this also true of the previously discussed readline approach, though? Or was this just intending to differentiate the for[/tt[ approach from [tt]readlines, which obviously reads the entire file at once?

  • 13.4: There's a section of 13.4 which deals primarily with binary data ("On some occasions… reads the rest of the file as a single piece of data"); it would make more sense to me to move this to the next section ("13.4.1 Using binary mode") and keeping 13.4 exclusively focused on text data. In fact, it may even make sense to just change 13.4.1 to 13.5 so you have two distinct sections for reading text data and reading binary data. Outside of that one segment, these are already neatly separated.

  • 13.7: I'd recommend separating out the discussion of s(trings) from the length of repetition; e.g., "Any of these may be preceded by an integer to indicate the number of values; in this case, '4s' indicates a string consisting of four characters." That explains the current record format, but also clarifies the overall behavior better.

  • 13.8: I'd recommend introducing pickling as e.g. "binary (de)serialization" and possibly tying it back to the concept of "object persistence" since these are terms developers from other languages might be more familiar with. (You do mention serialization in the next section, 13.8.1, in regard to JSON.) I could see these being introduced in these first paragraph to quickly establish a shared vocabulary.

  • 13.8: After the second code block, it'd be useful to explicitly point out that pickles are loaded FIFO; this is inferred later when discussing pickling a dictionary ("This also has the advantage…"), but was an immediate question I had when I saw the repeated pickle.load(file) statements.

  • 14.1.2: This entire subsection contains valuable content, but it doesn't exactly describe user-defined exceptions,
    but rather conditional handling of different exceptions. I recommend changing the subsection title to better reflect the content.

  • 14.2: In the Easier to ask forgiveness than permission callout box, it may be worth noting that the reason for LBYL is that, in many languages, raising exceptions had traditionally been a fairly expensive operation, and thus est avoided if the scenario can be detected ahead of time. With Python, raising exceptions and triggering the alternate execution path doesn't add significant overhead.

  • 14.2.5: It'd be useful to provide an example of the argument parameter in the assert example to illustrate that it's passed as an explanation of the assertion.

  • 14.2.8: To better round out the code sample, and illustrate the point, it would be useful to provide pseudocode for what one of the function parameter references might look like.

  • 14.3: I'm having trouble following the context of the "Context Managers using with" section (no pun intended). Context managers were previously discussed, and outside of using a try/finally statement in the example, the content doesn't really relate to throwing or handling exceptions.

  • 15.6: When you say, "On the other hand, the use of super can be tricky in more complex cases", it would be useful to provide an example. For instance, I assume one example would be multiple inheritance, so you might add "such as multiple inheritance, which is discussed more in section 15.3".

  • 15.11: Listing 15.3 and the subsequent analysis is probably unavoidably overwhelming, due to the complex nature of inheritance rules, but it might be easier to digest if the variable names were spelled out (e.g., module_variable, superclass_private_variable, class_method). Yes, this would be longer, but it'd avoid the need to annotate these, or constantly translate between the variables and their meaning. It would also help disambiguate between e.g. mv (module variable) and m (method).

  • 15.11: Since there's only one instance, self.siv should not need to be assigned using SC.siv, as suggested; that only applies to class and static members, right?

  • 15.14: In the bullet point, "All Python methods are virtual", the subsequent description better describes that they're public. Virtual usually implies that the methods can be overwritten in subclasses—and, if they are, then calls to that method from superclasses will call the overwritten version.

  • 16.1: I recommend adding "or substituting" in the opening summary, since this is such a key part of how regular expressions are used. E.g., "A regular expression (RE) is a way of recognizing and often extracting or even substituting data based on certain patterns of text" (I also replaced "from" with "based" since it doesn't make sense to "substitute from").

  • 16.2: In the Quick Check, searching for negative numbers might be a bit of a challenge for readers new to regular expressions without first introducing the special ? character (which is covered later in the chapter). Though, admittedly, I'm sure this is an easy hurdle to jump with a little aid from Google, or they can just wait until Section 16.4.

  • 16.3.1: For clarity, and to really reinforce the point, consider the following amendment: "…the \t and \n sequences aren't interpreted by Python as tabs or newlines but are left as two-string character sequences beginning with a backslash; this leaves them intact so that they can be properly interpreted as special characters by the regular expression module" to the end of the second paragraph: "

  • 16.4: Of course, in a real-world application we might also have to deal with multi-part first names, such as "Mary Anne", which would be challenging to address via this example! I really appreciated that you start off simple, then introduce complexities such as country code and different formatting standards later on; it's a nice approach.

  • 16.5: I really appreciate that you base the instruction off of named groups and callback-based substitutions. That said, I expect developers are going to encounter the (unfortunately more common) indexed-based approach in real-world applications. Given that, it may be worth including a quick callout box describing \n substitution string method—or, at least,
    the \g<num> method for working with named groups.

  • 17.4: It'd be useful to provide a more concrete example of duck typing in practice, in terms of how to evaluate the code. Is this just evaluating the members of a class to confirm that it has a method before executing it? Is it trying to call a method, and then handling the exception if it doesn't? Does it attempt to validate the output with type checking, to ensure it's the expected data type? Some additional detail would be useful. (The remainder of the chapter provides examples of how to implement "ducks" via the special method attributes, but this doesn't provide insight into how to implement duck typing itself.

  • 17.7.1: To reinforce a previous point, consider appending: "A for loop catches IndexError exceptions and handles them by exiting the loop. This is how for loops are terminated when used with normal lists or sequences—and is also a good illustration of how exceptions can be used for gracefully handling events that aren't necessarily errors, or which could otherwise be preemptively."

  • 17.11: In the second bullet, it would be useful to provide a couple of examples of these classes, beyond __str__() and the list methods.

  • 18.1 It may be worth distinguishing between a package, as a collection of modules, and a package as a distributable container, as accessible via e.g. pip. (So far as I understand at this point, there is overlap between these, but they are not synonymous, and that ambiguity in terminology might cause confusion.) Similarly, given this potential confusion, it may be useful to a nod to package management (e.g., via pip) and dependency management (e.g., via pipenv) in a callout, with a reference to the subsequent chapter that discusses those.

  • 18.3 Is "from mathproj.comp import c1" needed in Listing 18.5? The code doesn't call e.g. mathproj.comp.c1.x, so shouldn't need a reference to that module.

  • 18.3 This may speak to my own ignorance, but what is the difference between "exiting and restarting the program"
    and "just closing and reopening its Shell window" when using the IDLE? I assumed closing the IDLE would shut down the Python interpreter, thus forcing the program to restart. (Disclaimer: I primarily use IPython for interactive sessions, so may be missing something specific to the IDLE.)


  • Thanks again for all of the effort you've put into this book, and also for considering the above suggestions (should you have time!).

    Jeremy

    naomi.ceder (104) [Avatar] Offline
    #2
    Typos and Suggestions (Chapters 1-6)
    HI Jeremy!

    Thank you so much for taking the time to send all of this! As it happens I'm just about to start reviewing the final corrections, so anything I receive over the next several days can easily go in. I'll certainly make sure that all of your notes are addressed.

    I'm really grateful for anything that will result in a better book, so thanks again!

    And thank you so much for your kind words!

    Cheers,
    Naomi

    Jeremy Caney (28) [Avatar] Offline
    #3
    Typos and Suggestions (Chapters 1-6)
    Naomi—

    That's good to hear! I'll step up my reading schedule to see how much I can cover in the next few days. In the meantime, I've updated the original post with edits to the end of Chapter 6; I previously only had one comment on Chapter 6—from Section 6.3.3—so everything else related to Chapter 6 is new feedback. (Forewarning, some of the "Readability" feedback is a bit nit-picky; I think the suggestions improve the flow, but they're certainly not a priority.)

    Jeremy
    naomi.ceder (104) [Avatar] Offline
    #4
    Typos and Suggestions (Chapters 1-6)
    Hi Jeremy,

    Thanks for the effort.

    As I said, I'll consider all of the suggestions seriously.

    Cheers,
    Naomi
    Jeremy Caney (28) [Avatar] Offline
    #5
    Typos and Suggestions (Chapters 1-7)
    Naomi—FYI: I've added edits for Chapter 7. I've also underscored suggested changes to make it easier to see what's different.
    Jeremy Caney (28) [Avatar] Offline
    #6
    Typos and Suggestions (Chapters 1-8)
    FYI: I've updated the original post with suggestions from Chapter 8. Let me know when you're done with edits, and I'll stop making suggestions. (I imagine it'll take me another week to finish the book, by which point I imagine you'll have completed the manuscript.)
    naomi.ceder (104) [Avatar] Offline
    #7
    Typos and Suggestions (Chapters 1-8)
    Thanks! I will probably be done with the edits in the next few days, but will let you know.

    However, if you find any big errors, don't hesitate to let me know - we can fix the really problematic ones even after this phase.

    Again, thank you for taking the time to pass those along!

    Cheers,
    Naomi
    Jeremy Caney (28) [Avatar] Offline
    #8
    Typos and Suggestions (Chapters 1-8)
    Naomi—Good to know! I've updated the post to include Chapter 9 feedback. Most of it is pretty small (e.g., a couple of variables that should be monospaced). The two big items are under Content Suggestions, where I recommend further clarifying how yield works, and also differentiating the @ decorator syntax from the Decorator Pattern to avoid confusing people familiar with GoF definition.
    Jeremy Caney (28) [Avatar] Offline
    #9
    Typos and Suggestions (Chapters 1-10)
    FYI: I've updated this with feedback from Chapter 10. I'm also about half way through Chapter 11, and hope to have that completed soon.
    Jeremy Caney (28) [Avatar] Offline
    #10
    Typos and Suggestions (Chapters 1-11)
    FYI: I've completed Chapter 11, and updated the original post. There was a lot of feedback for this chapter, including a couple of higher priority typos (such as missing or extraneous words)—though no technical errors that I was aware of.

    As an aside, this was a really useful chapter for me, as I've primarily used Python as modules, and never as scripts, so I learned quite a bit of new material here. Further, while I've used the if __name__ == '__main__' syntax for the few scripts I've written, I always thought it was peculiar—this chapter helped me understand exactly what it's doing, and why it makes sense if the script is also to be used as a module.
    naomi.ceder (104) [Avatar] Offline
    #11
    Typos and Suggestions (Chapters 1-11)
    Thanks! You're really doing a lot of work here!

    Just so you know, I'm using your notes to cross-check against the copyediting that's also going on. Between the two of you, it's really making for a stronger book.

    Cheers,
    Naomi
    Jeremy Caney (28) [Avatar] Offline
    #12
    Typos and Suggestions (Chapters 1-12)
    Naomi—It's possible I'm going overboard. Before I became a software developer I was a copy editor, so once I get into that mode, I become pretty focused! I'm glad to hear it's helpful, though. Hopefully the format is making it easy to cross-reference.

    I just completed Chapter 12. I mention this in Content Suggestions, but it's worth calling out:
    Overall, I found Chapter 12 a bit confusing due to the jumping back-and-forth between os and pathlib. Since not all aspects of os were covered in the pathlib sections, I found myself uncertain whether os was still needed if pathlib was being used, and whether all of the best practices for os carried forward as well. Ideally, this would be clearer if the chapter was primarily written from the perspective of pathlib, with references to best practices and os when appropriate, and then included ancillary sections for legacy support using exclusively os. That would probably be a pretty involved refactoring, however, and may not be worth the effort.
    naomi.ceder (104) [Avatar] Offline
    #13
    Typos and Suggestions (Chapters 1-12)
    Ah, that explains it! Thanks again for taking the time!

    I don't think at this point it makes sense to re-work ch 12, but I do see your point...

    Cheers,
    Naomi
    Jeremy Caney (28) [Avatar] Offline
    #14
    Typos and Suggestions (Chapters 1-12)
    Naomi—That makes sense regarding Chapter 12. I've now finished Chapter 13, and updated the post with suggestions.

    I enjoyed this remark, "If you’re an extremely friendly sort of person, and your address book is too big for this, it would be better to use shelve and not worry about this".

    Aside, my wife’s a mathematician, and has been increasingly finding herself working in Python. She’s not familiar with shelves, though, so I can’t wait to introduce her to them. I imagine they’d be especially helpful for developing a persistent, low-memory cache across multiple runs to help speed up some of her numerics. I'll certainly be using them for that purpose in some of my bioinformatics work (I also wasn't familiar with them).

    Jeremy
    447665 (9) [Avatar] Offline
    #15
    Typos and Suggestions (Chapters 1-12)
    3.2.1 Numbers: pp.19 : “ …and the “imaginary” part with x.image. “ change “x.image” to x.imag. Also the font type should change accordingly.

    3.3.2 The if-elif-else statement: “The block of code after the first true condition (of an if or an elif) is executed. If none of the conditions is true, the block of code after the else is executed:” The word “true” should not be fixed-width-font. Otherwise use the reserved words “True”.

    3.3.7 “Here with establishes a context manager to which wraps the open function and the block “that follows.” The “to which” are grammatically ambiguous. Also I am wondering if the indentation for “for line in f” in the equivalent code
    "filename = "myfile.txt"
    try:
    f = open(filename, "r")
    for line in f:
    print(f)
    except Exception as e:
    raise e
    finally:
    f.close()"
    is correct or not?
    naomi.ceder (104) [Avatar] Offline
    #16
    Typos and Suggestions (Chapters 1-12)
    Got those for Ch 3, thanks!
    naomi.ceder (104) [Avatar] Offline
    #17
    Typos and Suggestions (Chapters 1-12)
    Jeremy, I'm glad to hear it!. You're right about shelves, they're handy for the sort of caching/persistence you describe... so long as there aren't too many insertions, particularly as they get larger.
    Jeremy Caney (28) [Avatar] Offline
    #18
    Typos and Suggestions (Chapters 1-12)
    Naomi—I've finished Chapter 14. Much of the feedback relates to wordiness, which is admittedly difficult to avoid when you're talking about exceptions, exception catchers, exception handlers, &c. Nonetheless, I recommended removing a number of redundancies that were inferred by the context, and helped the sentences flow more naturally.

    The only major piece of feedback I had was regarding section 14.3 Context managers using with:
    14.3: I'm having trouble following the context of the "Context managers using with" section (no pun intended). Context managers were previously discussed, and outside of using a try/finally statement in the example, the content doesn't really relate to throwing or handling exceptions.
    The content was useful, it just felt out-of-place, and didn't add much new to the previous coverage of context managers.

    Aside, I laughed (out loud) at the following:

  • 14.2: "The actual error reported isn’t as serious as those other ones.

  • 14.2.8: "Trying to develop this ability without the use of exceptions is a highly educational exercise.

  • I appreciate it when authors sprinkle technical books with a bit of subtle humor.
    Jeremy Caney (28) [Avatar] Offline
    #19
    Typos and Suggestions (Chapters 1-15)
    Naomi—I've also finished typing up feedback for Chapter 15. Despite this being one of the longer chapters in the book, I found surprisingly few items of note. The vast majority of my feedback just pertains for formatting issues (e.g., non-monospaced identifiers, missing spaces, &c.). I had thought I had a reasonably good handle on classes in Python before reading this chapter, but it turns out there was quite a bit I didn't know! For example, I didn't know about class and static methods, or the rules of multiple inheritance.

    The only major piece of feedback in this chapter pertained to Section 15.11:
    15.11: Listing 15.3 and the subsequent analysis are probably unavoidably overwhelming, due to the complex nature of inheritance rules, but it might be easier to digest if the variable names were spelled out (e.g., module_variable, superclass_private_variable, class_method). Yes, this would be longer, but it'd avoid the need to annotate these, or constantly translate between the variables and their meaning. It would also help disambiguate between e.g. the m in mv (module variable) and m, m2 (method).

    Jeremy Caney (28) [Avatar] Offline
    #20
    Typos and Suggestions (Chapters 1-16)
    Naomi—I've updated the post to include feedback from Chapter 16.

    As a general point of feedback, the entirety of this chapter provides a remarkably accessible introduction to a topic that many developers seem to find inscrutable. The building up of concepts across the chapter, but especially in Section 16.2, is really nicely done. I've repeatedly found it challenging to introduce junior developers to regular expressions in part because the syntax seems so daunting; even if they're not working in Python, I'm going to recommend they read this chapter, since it so succinctly introduces the concepts (acknowledging that there are some syntactical differences between Python and other languages that they'll need to be made aware of).

    Jeremy
    Jeremy Caney (28) [Avatar] Offline
    #21
    Typos and Suggestions (Chapters 1-17)
    Naomi—I've also updated this to include Chapter 17. I found this chapter really useful and interesting; it was largely new information for me.

    The one part that tripped me up is that most of the subsections are not self-contained; this leads to subsections ending abruptly or with unanswered questions. There's nothing wrong with this, but since most of the other subsections in your book can be read and referenced non-sequentially, this was unexpected. You do say, at the end of 17.5 What is a special method attribute?:
    The rest of this chapter covers longer examples using special method attributes.
    Nonetheless, I'd consider adding in a few more phrases like that at the end of the chapters to remind the reader that this is an example you're going to keep iterating over to address remaining issues; e.g., acknowledge the open questions, and use that as a lead in to the next chapter.

    Aside, I appreciated this remark:
    A type object is another kind of Python object whose only outstanding feature is the confusion its name sometimes causes. Saying a type object is of type <class 'type'> has about the same degree of larity as the old Abbott and Costello "Who's on First?" comedy routine.
    It's especially relevant as my company built an open source CMS which ends up with a lot of similar problems, since it's broken down into Content Types. Since content types themselves are configured using the CMS, each content type ends up being composed of a content type called "content type". It can lead to some really confusing conversations, and inevitably invites references to Abbott and Costello.

    Jeremy
    447665 (9) [Avatar] Offline
    #22
    Typos and Suggestions (Chapters 1-17)
    In 17.5 What is a special method attribute?: right prior to Listing 17.1, "Our definition looks something like listing 20.1" seems to refer to the listing 17.1.

    In 17.6 "with a double semicolon ( : : ) between the fields" change semi-colon or colons?
    naomi.ceder (104) [Avatar] Offline
    #23
    Typos and Suggestions (Chapters 1-17)
    Thanks for the kind words and for the corrections!
    Jeremy Caney (28) [Avatar] Offline
    #24
    Naomi—I've completed Chapter 18, if you're still in a stage that you can accept corrections! (If you're not, do let me know and I'll stop updating this post.) I didn't have too much feedback for this chapter; the only major item was:
    18.1 It may be worth distinguishing between a package, as a collection of modules, and a package as a distributable container, as accessible via e.g. pip. (So far as I understand at this point, there is overlap between these, but they are not synonymous, and that ambiguity in terminology might cause confusion.) Similarly, given this potential confusion, it may be useful to give a nod to package management (e.g., via pip) and dependency management (e.g., via pipenv) in a callout, with a reference to the subsequent chapter that discusses those.
    Aside, I meant to mention this earlier, but I really like how you pepper the text with references such as: “We’ll talk more about __init__.py files in a bit; for now, all you need to know is that they’re run automatically whenever a package is first loaded” (18.3.2). Comments like this really help set expectations and quiet outstanding questions or points of confusion. And, of course, when using the book as a reference they also make it dramatically easier to cross-reference relevant material.

    Finally, I also appreciated this comment: “Unfortunately, all isn’t this simple in practice because details intrude to make their use more complex than their theory” (18.2); I feel like we can generalize that for just about anything!
    naomi.ceder (104) [Avatar] Offline
    #25
    Thanks, Jeremy!

    Yes, at this point I have to move on from author review of copy edits, so unless it's a big deal, getting changes in for the last chapters probably won't be worth it.

    Again, thanks for taking the time to send things in - I appreciate anything that will make it a better book.

    Also, thanks for the kind words - that's always encouraging to hear, particularly in this stage of the process.

    Thanks again,
    Naomi
    447665 (9) [Avatar] Offline
    #26
    15.8 Recap-basics of Python classes.
    In definition of class Circle "all_circles.append(self) #E" should be "self.__class__.all_circles.append(self) #E"
    Jeremy Caney (28) [Avatar] Offline
    #27
    Naomi—No problem. I do have a number of typo and formatting issues I’ve flagged from the remaining chapters, and am happy to send them over should you end up with time. Otherwise, I suspect your proof-reader or editor probably caught most of them. (I haven’t had too many additional readability or content suggestions since my last update; mostly just small spelling errors or inconsistent monospacing.)

    I’m sure you’re quite eager to get this third edition published. It’s remarkable how much effort a book of this scope requires—though the community will certainly be better off for it. I’ve learned a lot so far, and have already been incorporating the learnings into a RaspberryPi project I’ve been working on with my wife.

    Jeremy
    naomi.ceder (104) [Avatar] Offline
    #28
    Thanks again! Yes, indeed, I'll be happy when this is through the process. smilie

    Cheers,
    Naomi