Python is one of the most widely used programming languages in the world. It is used everywhere from primary school education to workaday web development, to the most advanced scientific research institutes of the world. However, like all programming languages, Python has a collection of "Pythonic" ways of accomplishing tasks that are easy to overlook, especially when habits are borrowed wholesale from work in other programming languages.
Better Python Code is a guide to Pythonic programming. The book presents common mistakes that Python developers make--even Python developers who have used the language for years--often because Python sometimes presents "attractive nuisances." Throughout, the book is a guide to better programming in the core Python language.
Each section shows a concrete but concise example of some misunderstanding or bad habit in action. Each section contains a description of what is wrong with the sample code and a suggestion for one or more better ways to code equivalent functionality without the initial pitfall. Every pitfall addressed in this book reflects foibles, errors, and misunderstandings that the author as seen in concrete, widely used code bases written by experienced developers, over his 25 years of writing Python.
The sections of this book each present some mistake, pitfall, or foible that developers can easily fall into, and are accompanied by descriptions of ways to avoid making them. At times those solutions simply involve a minor change in “spelling,” but in most cases they require a nuance of thought and design in your code. Many of the discussions do something else as well…
I do not hope only to show you something you did not know, but in a great many cases I hope to show you something about which you did not know there was something to know. I believe that the most effective writing and teaching conveys to readers or students not only information, but also good ways of thinking about problems and reasoning about their particular solutions. The info boxes, footnotes, and silly digressions within this book all hope to allow you to think deeper about a particular domain, or a particular task, or a particular style of programming.
There is no need to read this book from cover to cover (but I believe that readers who do so will benefit). Each chapter addresses a related cluster of concepts, but stands alone. Moreover, each section within a chapter is also self-contained. Each can be read independently of the others, and most readers will learn something interesting in each one. Some of the sections are more advanced than others, but even in those that seem introductory, I think you will find nuances you did not know. And even in those that seem advanced, I hope you will find the discussions accessible and enlightening.
Both beginners and developers with decades of experience will learn to correct limitations in the code they write after reflecting on these discussions.
Author(s): David Mertz
Publisher: Addison-Wesley
Year: 2024
Language: English
Pages: 510
Cover Page
About This eBook
Halftitle Page
Title Page
Copyright Page
Pearson’s Commitment to Diversity, Equity, and Inclusion
Dedication Page
Contents
Foreword
Preface
About the Book
Code Samples
Obtaining the Tools Used in This Book
Other Useful Tools
Acknowledgments
About the Author
Introduction
1. Looping Over the Wrong Things
1.1 (Rarely) Generate a List for Iteration
1.2 Use enumerate() Instead of Looping Over an Index
1.3 Don’t Iterate Over dict.keys() When You Want dict.items()
1.4 Mutating an Object During Iteration
1.5 for Loops Are More Idiomatic Than while Loops
1.6 The Walrus Operator for “Loop-and-a-Half” Blocks
1.7 zip() Simplifies Using Multiple Iterables
1.8 zip(strict=True) and itertools.zip_longest()
1.9 Wrapping Up
2. Confusing Equality with Identity
2.1 Late Binding of Closures
2.2 Overchecking for Boolean Values
2.3 Comparing x == None
2.4 Misunderstanding Mutable Default Arguments
2.5 Copies versus References to Mutable Objects
2.6 Confusing is with == (in the Presence of Interning)
2.7 Wrapping Up
3. A Grab Bag of Python Gotchas
3.1 Naming Things
3.2 Quadratic Behavior of Naive String Concatenation
3.3 Use a Context Manager to Open a File
3.4 Optional Argument key to .sort() and sorted()
3.5 Use dict.get() for Uncertain Keys
3.6 Wrapping Up
4. Advanced Python Usage
4.1 Comparing type(x) == type(y)
4.2 Naming Things (Revisited)
4.3 Keep Less-Used Features in Mind
4.4 Type Annotations Are Not Runtime Types
4.5 Wrapping Up
5. Just Because You Can, It Doesn’t Mean You Should…
5.1 Metaclasses
5.2 Monkeypatching
5.3 Getters and Setters
5.4 It’s Easier to Ask for Forgiveness Than Permission
5.5 Structural Pattern Matching
5.6 Regular Expressions and Catastrophic Backtracking
5.7 Wrapping Up
6. Picking the Right Data Structure
6.1 collections.defaultdict
6.2 collections.Counter
6.3 collections.deque
6.4 collections.ChainMap
6.5 Dataclasses and Namedtuples
6.6 Efficient Concrete Sequences
6.7 Wrapping Up
7. Misusing Data Structures
7.1 Quadratic Behavior of Repeated List Search
7.2 Deleting or Adding Elements to the Middle of a List
7.3 Strings Are Iterables of Strings
7.4 (Often) Use enum Rather Than CONSTANT
7.5 Learn Less Common Dictionary Methods
7.6 JSON Does Not Round-Trip Cleanly to Python
7.7 Rolling Your Own Data Structures
7.8 Wrapping Up
8. Security
8.1 Kinds of Randomness
8.2 Putting Passwords or Other Secrets in “Secure” Source Code
8.3 “Rolling Your Own” Security Mechanisms
8.4 Use SSL/TLS for Microservices
8.5 Using the Third-Party requests Library
8.6 SQL Injection Attacks When Not Using DB-API
8.7 Don’t Use assert to Check Safety Assumptions
8.8 Wrapping Up
9. Numeric Computation in Python
9.1 Understanding IEEE-754 Floating Point Numbers
9.2 Numeric Datatypes
9.3 Wrapping Up
A. Appendix: Topics for Other Books
A.1 Test-Driven Development
A.2 Concurrency
A.3 Packaging
A.4 Type Checking
A.5 Numeric and Dataframe Libraries
Index
Code Snippets