Effective Python 2nd Edition: What’s new?

Effective Python by Brett Slatkin is a book filled with best practices of the Python programming language. I devoured the first edition as an ebook and was eager to buy the second edition as a physical book. Having skimmed through it, I was already satisfied. The new edition features updates, the removal of all Python 2 specific hints and workarounds. More specifically, it concentrates on language features of Python 3 up to and including Python 3.8.

However, I was a little confused that there was no tabular information about the additions and the changes. Certainly, it looks like each item was changed in one way or another (as most items in the first edition contained workarounds for Python 2). But if you are like me, owning the first edition of the book and wondering if the new content will be worth it, this blog post got you covered.

In case you want to do the comparison yourself, there is a table of contents of the 2nd edition on the main page of the official web site of the book.

Entirely new items in Effective Python 2nd Edition

There are 27 entirely new items.

  • 4. Prefer Interpolated F-Strings Over C-style Format Strings and str.format
  • 6. Prefer Multiple Assignment Unpacking Over Indexing
  • 10. Prevent Repetition with Assignment Expressions
  • 13. Prefer Catch-All Unpacking Over Slicing
  • 14. Sort by Complex Criteria Using the key Parameter
  • 15. Be Cautious When Relying on dict Insertion Ordering
  • 16. Prefer get Over in and KeyError to Handle Missing Dictionary Keys
  • 17. Prefer defaultdict Over setdefault to Handle Missing Items in Internal State
  • 18. Know How to Construct Key-Dependent Default Values with __missing__
  • 19. Never Unpack More Than Three Variables When Functions Return Multiple Values
  • 29. Avoid Repeated Work in Comprehensions by Using Assignment Expressions
  • 33. Compose Multiple Generators with yield from
  • 34. Avoid Injecting Data into Generators with send
  • 35. Avoid Causing State Transitions in Generators with throw
  • 36. Consider itertools for Working with Iterators and Generators
  • 51. Prefer Class Decorators Over Metaclasses for Composable Class Extensions
  • 56. Know How to Recognize When Concurrency Is Necessary
  • 57. Avoid Creating New Thread Instances for On-demand Fan-out
  • 58. Understand How Using Queue for Concurrency Requires Refactoring
  • 59. Consider ThreadPoolExecutor When Threads Are Necessary for Concurrency
  • 61. Know How to Port Threaded I/O to asyncio
  • 62. Mix Threads and Coroutines to Ease the Transition to asyncio
  • 63. Avoid Blocking the asyncio Event Loop to Maximize Responsiveness
  • 74. Consider memoryview and bytearray for Zero-Copy Interactions with bytes
  • 79. Encapsulate Dependencies to Facilitate Mocking and Testing
  • 89. Consider warnings to Refactor and Migrate Usage
  • 90. Consider Static Analysis via typing to Obviate Bugs

Items heavily updated in Effective Python 2nd Edition

Most updates to existing items are to only cover code samples for Python 3.7 with some notable exceptions that show 3.8 exclusive samples (the most prominent being the introduction to the walrus operator in items 10 and 29). Most noteworthy, the first item Know Which Version of Python You’re Using already makes it clear at the end of the first paragraph:

This book does not cover Python 2.

Keeping this in mind, we expect to see some updates. For instance, Item 3: Know the Differences Between bytes and str does not mention the Python 2 exclusive unicode anymore. Even so, there are certain items that have been updated so much that they contain new advice because of newly added language features. In particular, I want to mention the following items in this regard.

  • 48. Validate Subclasses with __init_subclass__ (former Item 33: Validate Subclasses with Metaclasses)
  • 49. Register Class Existence with __init_subclass__ (former Item 34: Register Class Existence with Metaclasses)
  • 50. Annotate Class Attributes with __set_name__ (former Item 35: Annotate class attributes with Metaclasses)
  • 60. Achieve Highly Concurrent I/O with Coroutines (former Item 40: Consider Coroutines to Run Many Functions Concurrently)

While the first three items in this list introduce new language features restricting the use cases for Metaclasses, the last one was updated to show the new way of defining Coroutines using the asyncio built-in module. Since this last item and the preceding items 56-59 feature Conway’s Game of Life as an example, you might also argue that item 60 belongs in the next section.

Items that have been split up into multiple more elaborate items

There are two items from the first edition that have been split into multiple items in the 2nd edition:

  • Item 46: Use Built-In Algorithms and Data Structures has been split up into
    • 71. Prefer deque for Producer–Consumer Queues
    • 72. Consider Searching Sorted Sequences with bisect
    • 73. Know How to Use heapq for Priority Queues
  • Item 56: Test Everything with Unittest has been split up into
    • 76. Verify Related Behaviors in TestCase Subclasses
    • 77. Isolate Tests from Each Other with setUp, tearDown, setUpModule, and tearDownModule
    • 78. Use Mocks to Test Code with Complex Dependencies

Item 46 from the first edition had more of an overview character, introducing data types from built-in modules. The corresponding items from the 2nd edition are more elaborate and provide an in-depth view with more code samples and example use cases.

Considering the importance of testing generally and particularly in dynamically typed languages such as Python, I found item 56 from the first edition to be too brief. In contrast, the new items are much more elaborate on the best practices in testing. Above all, item 78 about Mocks is a precious addition, giving an example of how to use the unittest.mock built-in module to write unit tests for code depending on a database connection.

Conclusion

To sum it up, Effective Python 2nd Edition adds a lot of new content in comparison to its first edition. More precisely, there are 27 entirely new items. Additionally, two items have been split up into multiple, more elaborate items so that the new edition clocks in at 90 items in comparison to 59 items from the first edition.

Leave a Reply

Your email address will not be published. Required fields are marked *