Acknowledgments | p. xix |
Introduction | p. xxi |
Who Should Read This Book and Why | p. xxii |
About This Book | p. xxii |
Your Programming Journey | p. xxiv |
Getting Started | p. 1 |
Dealing with Errors and Asking for Help | p. 3 |
How to Understand Python Error Messages | p. 4 |
Examining Tracebacks | p. 4 |
Searching for Error Messages | p. 7 |
Preventing Errors with Linters | p. 8 |
How to Ask for Programming Help | p. 9 |
Limit Back and Forth by Providing Your Information Upfront | p. 10 |
State Your Question in the Form of an Actual Question | p. 10 |
Ask Your Question on the Appropriate Website | p. 10 |
Summarize Your Question in the Headline | p. 11 |
Explain What You Want the Code to Do | p. 11 |
Include the Full Error Message | p. 11 |
Share Your Complete Code | p. 11 |
Make Your Code-Readable with Proper Formatting | p. 12 |
Tell Your Helper What You've Already Tried | p. 13 |
Describe Your Setup | p. 13 |
Examples of Asking a Question | p. 14 |
Summary | p. 14 |
Environment Setup and the Command Line | p. 17 |
The Filesystem | p. 18 |
Paths in Python | p. 18 |
The Home Directory | p. 19 |
The Current Working Directory | p. 19 |
Absolute vs. Relative Paths | p. 20 |
Programs and Processes | p. 21 |
The Command Line | p. 22 |
Opening a Terminal Window | p. 23 |
Running Programs from the Command Line | p. 23 |
Using Command Line Arguments | p. 24 |
Running Python Code from the Command Line with -c | p. 26 |
Running Python Programs from the Command Line | p. 26 |
Running the py.exe Program | p. 26 |
Running Commands from a Python Program | p. 27 |
Minimizing Typing with Tab Completion | p. 27 |
Viewing the Command History | p. 28 |
Working with Common Commands | p. 28 |
Environment Variables and Path | p. 35 |
Viewing Environment Variables | p. 36 |
Working with the Path Environment Variable | p. 36 |
Changing the Command Line's PATH Environment Variable | p. 37 |
Permanently Adding Folders to PATH on Windows | p. 38 |
Permanently Adding Folders to PATH on macOS and Linux | p. 39 |
Running Python Programs Without the Command Line | p. 39 |
Running Python Programs on Windows | p. 40 |
Running Python Programs on macOS | p. 41 |
Running Python Programs on Ubuntu Linux | p. 41 |
Summary | p. 42 |
Best Practices, Tools, and Techniques | p. 43 |
Code Formatting with Black | p. 45 |
How to Lose Friends and Alienate Co-Workers | p. 46 |
Style Guides and PEP 8 | p. 46 |
Horizontal Spacing | p. 47 |
Use Space Characters for Indentation | p. 47 |
Spacing Within a Line | p. 48 |
Vertical Spacing | p. 51 |
A Vertical Spacing Example | p. 51 |
Vertical Spacing Best Practices | p. 52 |
Black: The Uncompromising Code Formatter | p. 53 |
Installing Black | p. 54 |
Running Black from the Command Line | p. 54 |
Disabling Black for Parts of Your Code | p. 57 |
Summary | p. 58 |
Choosing Understandable Names | p. 59 |
Casing Styles | p. 60 |
PEP 8's Naming Conventions | p. 61 |
Appropriate Name Length | p. 61 |
Too Short Names | p. 61 |
Too Long Names | p. 63 |
Make Names Searchable | p. 64 |
Avoid Jokes, Puns, and Cultural References | p. 64 |
Don't Overwrite Built-in Names | p. 65 |
The Worst Possible Variable Names Ever | p. 66 |
Summary | p. 67 |
Finding Code Smells | p. 69 |
Duplicate Code | p. 70 |
Magic Numbers | p. 71 |
Commented-Out Code and Dead Code | p. 74 |
Print Debugging | p. 75 |
Variables with Numeric Suffixes | p. 76 |
Classes That Should Just Be Functions or Modules | p. 77 |
List Comprehensions Within List Comprehensions | p. 77 |
Empty except Blocks and Poor Error Messages | p. 79 |
Code Smell Myths | p. 80 |
Myth: Functions Should Have Only One Return Statement at the End | p. 80 |
Myth: Functions Should Have at Most One try Statement | p. 81 |
Myth: Flag Arguments Are Bad | p. 82 |
Myth: Global Variables Are Bad | p. 82 |
Myth: Comments Are Unnecessary | p. 83 |
Summary | p. 84 |
Writing Pythonic Code | p. 87 |
The Zen of Python | p. 88 |
Learning to Love Significant Indentation | p. 91 |
Commonly Misused Syntax | p. 92 |
Use enumerate() Instead of range() | p. 92 |
Use the with Statement Instead of open() and close() | p. 93 |
Use is to Compare with None Instead of ==. | p. 94 |
Formatting Strings | p. 95 |
Use Raw Strings If Your String Has Many Backslashes | p. 95 |
Format Strings with F-Strings | p. 96 |
Making Shallow Copies of Lists | p. 97 |
Pythonic Ways to Use Dictionaries | p. 98 |
Use get() and Setdefault() with Dictionaries | p. 98 |
Use Collections.defaultdict for Default Values | p. 99 |
Use Dictionaries Instead of a switch Statement | p. 100 |
Conditional Expressions: Python's "Ugly" Ternary Operator | p. 101 |
Working with Variable Values | p. 103 |
Chaining Assignment and Comparison Operators | p. 103 |
Checking Whether a Variable Is One of Many Values | p. 103 |
Summary | p. 104 |
Programming Jargon | p. 107 |
Definitions | p. 108 |
Python the Language and Python the Interpreter | p. 108 |
Garbage Collection | p. 109 |
Literals | p. 109 |
Keywords | p. 110 |
Objects, Values, Instances, and Identities | p. 111 |
Items | p. 114 |
Mutable and Immutable | p. 114 |
Indexes, Keys, and Hashes | p. 117 |
Containers, Sequences, Mapping, and Set Types | p. 119 |
Dunder Methods and Magic Methods | p. 120 |
Modules and Packages | p. 120 |
Collables and First-Class Objects | p. 121 |
Commonly Confused Terms | p. 122 |
Statements vs. Expressions | p. 122 |
Block vs. Clause vs. Body | p. 123 |
Variable vs. Attribute | p. 124 |
Function vs. Method | p. 124 |
Iterable vs. Iterator | p. 125 |
Syntax vs. Runtime vs. Semantic Errors | p. 126 |
Parameters vs. Arguments | p. 128 |
Type Coercion vs. Type Casting | p. 128 |
Properties vs. Attributes | p. 128 |
Bytecode vs. Machine Code | p. 129 |
Script vs. Program, Scripting Language vs. Programming Language | p. 129 |
Library vs. Framework vs. SDK vs. Engine vs. API | p. 130 |
Summary | p. 131 |
Further Reading | p. 131 |
Common Python Gotchas | p. 133 |
Don't Add or Delete Items from a List While Looping Over It | p. 134 |
Don't Copy Mutable Values Without copy.copy() and copy.deepcopy() | p. 140 |
Don't Use Mutable Values for Default Arguments | p. 142 |
Don't Build Strings with String Concatenation | p. 144 |
Don't Expect sort() to Sort Alphabetically | p. 146 |
Don't Assume Floating-Point Numbers Are Perfectly Accurate | p. 147 |
Don't Chain Inequality != Operators | p. 149 |
Don't Forget the Comma in Single-Item Tuples | p. 150 |
Summary | p. 150 |
Esoteric Python Oddities | p. 153 |
Why 256 Is 256 but 257 Is Not 257 | p. 154 |
String Interning | p. 155 |
Python's Fake Increment and Decrement Operators | p. 156 |
All of Nothing | p. 157 |
Boolean Values Are Integer Values | p. 158 |
Chaining Multiple Kinds of Operators | p. 159 |
Python's Antigravity Feature | p. 160 |
Summary | p. 160 |
Writing Effective Functions | p. 161 |
Function Names | p. 162 |
Function Size Trade-Offs | p. 162 |
Function Parameters and Arguments | p. 165 |
Default Arguments | p. 165 |
Using * and ** to Pass Arguments to Functions | p. 166 |
Using * to Create Variadic Functions | p. 167 |
Using ** to Create Variadic Functions | p. 169 |
Using * and ** to Create Wrapper Functions | p. 171 |
Functional Programming | p. 172 |
Side Effects | p. 172 |
Higher-Order Functions | p. 174 |
Lambda Functions | p. 174 |
Mapping and Filtering with List Comprehensions | p. 175 |
Return Values Should Always Have the Same Data Type | p. 177 |
Raising Exceptions vs. Returning Error Codes | p. 178 |
Summary | p. 179 |
Comments, Docstrings, and Type Hints | p. 181 |
Comments | p. 182 |
Comment Style | p. 183 |
Inline Comments | p. 184 |
Explanatory Comments | p. 184 |
Summary Comments | p. 185 |
"Lessons Learned" Comments | p. 185 |
Legal Comments | p. 186 |
Professional Comments | p. 186 |
Codetags and TODO Comments | p. 187 |
Magic Comments and Source File Encoding | p. 187 |
Docstrings | p. 188 |
Type Hints | p. 190 |
Using Static Analyzers | p. 192 |
Setting Type Hints for Multiple Types | p. 194 |
Setting Type Hints for Lists, Dictionaries, and More | p. 195 |
Backporting Type Hints with Comments | p. 196 |
Summary | p. 197 |
Organizing Your Code Projects with Git | p. 199 |
Git Commits and Repos | p. 200 |
Using Cookiecutter to Create New Python Projects | p. 200 |
Installing Git | p. 202 |
Configuring Your Git Username and Email | p. 203 |
Installing GUI Git Tools | p. 203 |
The Git Workflow | p. 204 |
How Git Keeps Track of File Status | p. 204 |
Why Stage Files? | p. 206 |
Creating a Git Repo on Your Computer | p. 206 |
Adding Files for Git to Track | p. 208 |
Ignoring Files in the Repo | p. 209 |
Committing Changes | p. 210 |
Deleting Files from the Repo | p. 214 |
Renaming and Moving Files in the Repo | p. 215 |
Viewing the Commit Log | p. 216 |
Recovering Old Changes | p. 217 |
Undoing Uncommitted Local Changes | p. 218 |
Unstaging a Staged File | p. 218 |
Rolling Back the Most Recent Commits | p. 218 |
Rolling Back to a Specific Commit for a Single File | p. 219 |
Rewriting the Commit History | p. 220 |
GitHub and the git push Command | p. 221 |
Pushing an Existing Repository to GitHub | p. 222 |
Cloning a Repo from an Existing GitHub Repo | p. 222 |
Summary | p. 223 |
Measuring Performance and Big O Algorithm Analysis | p. 225 |
The timeit Module | p. 226 |
The cProfile Profiler | p. 228 |
Big O Algorithm Analysis | p. 230 |
Big O Orders | p. 230 |
A Bookshelf Metaphor for Big O Orders | p. 231 |
Big O Measures the Worst-Case Scenario | p. 235 |
Determining the Big O Order of Your Code | p. 237 |
Why Lower Orders and Coefficients Don't Matter | p. 238 |
Big O Analysis Examples | p. 239 |
The Big O Order of Common Function Calls | p. 242 |
Analyzing Big O at a Glance | p. 243 |
Big O Doesn't Matter When n Is Small, and n Is Usually Small | p. 244 |
Summary | p. 244 |
Practice Projects | p. 247 |
The Tower of Hanoi | p. 248 |
The Output | p. 249 |
The Source Code | p. 250 |
Writing the Code | p. 252 |
Four-in-a-Raw | p. 259 |
The Output | p. 259 |
The Source Code | p. 260 |
Writing the Code | p. 264 |
Summary | p. 271 |
Object-Oriented Python | p. 273 |
Object-Oriented Programming and Classes | p. 275 |
Real-World Analogy: Filling Out a Form | p. 276 |
Creating Objects from Classes | p. 278 |
Creating a Simple Class: WizCoin | p. 279 |
Methods, _init_(), and self | p. 280 |
Attributes | p. 282 |
Private Attributes and Private Methods | p. 282 |
The Type() Function and _qualname_Attribute | p. 284 |
Non-OOP vs. OOP Examples: Tic-Tac-Toe | p. 285 |
Designing Classes for the Real World Is Hard | p. 290 |
Summary | p. 291 |
Object-Oriented Programming and Inheritance | p. 293 |
How Inheritance Works | p. 294 |
Overriding Methods | p. 296 |
The super() Function | p. 297 |
Favor Composition Over Inheritance | p. 299 |
Inheritance's Downside | p. 301 |
The isinstance() and issubclass() Functions | p. 303 |
Class Methods | p. 304 |
Class Attributes | p. 306 |
Static Methods | p. 306 |
When to Use Class and Static Object-Oriented Features | p. 307 |
Object-Oriented Buzzwords | p. 307 |
Encapsulation | p. 307 |
Polymorphism | p. 308 |
When Not to Use Inheritance | p. 308 |
Multiple Inheritance | p. 309 |
Method Resolution Order | p. 311 |
Summary | p. 312 |
Pythonic OOP: Properties and Dunder Methods | p. 315 |
Properties | p. 316 |
Turning an Attribute into a Property | p. 316 |
Using Setters to Validale Data! | p. 319 |
Read-Only Properties | p. 320 |
When to Use Properties | p. 322 |
Python's Dunder Methods | p. 322 |
String Representation Dunder Methods | p. 323 |
Numeric Dunder Methods | p. 325 |
Reflected Numeric Dunder Methods | p. 328 |
In-Place Augmented Assignment Dunder Methods | p. 330 |
Comparison Dunder Methods | p. 332 |
Summary | p. 337 |
Index | p. 339 |
Table of Contents provided by Ingram. All Rights Reserved. |