# Fluent Python, second edition: the chapters that help FDEs read client code like its authors

> Data classes, type hints and concurrency models are new in the second edition, and code like this may well land on your desk in your first week at a client.

Original: https://fdetimes.net/en/books-courses/fluent-python-second-edition-for-fdes/

In the table of contents of Fluent Python's second edition, only four chapters carry the 🆕 mark: Data Class Builders (chapter 5), Type Hints in Functions (8), More About Type Hints (15) and Concurrency Models in Python (19). Luciano Ramalho, the book's author (O'Reilly, 2022), also substantially rewrote the chapters on concurrency.

Those changes line up with the work of a Forward Deployed Engineer. Picture your first week at a client: you are likely to spend much of it reading code someone else wrote, and that code will probably have type hints, data classes built with tooling, and pipelines that call APIs in parallel.

If so, the four new chapters may well match the kinds of code you most need to read quickly. The two examples on type hints and concurrency below show why, along with a reading order and what to do with each part.

## Who should open this book, and when?

This is not a beginner's book: both the ACCU reviewer and the hamatti.org blog say it is aimed at people who already have experience writing Python.

If you are just starting out, write real code for a few months before opening it. If you have written Python for a few years but still find yourself "translating" from Java or C#, do not read it cover to cover; follow the order in the diagram at the top of this article.

## First idea: an object's behaviour lives in its special methods

The book opens with the Python data model, then moves on to lists, dicts and sets. This is the foundation for reading idiomatic Python: double-underscore methods such as `__len__` and `__getitem__` decide how an object behaves when passed to built-in functions such as `len()`.

Take a hypothetical example: client code contains the line `len(batch)`, where `batch` is an instance of a custom class. Search for a method called `len` and you will find nothing; the answer lies in `__len__`. Once this way of looking becomes habit, you read an unfamiliar class by listing its special methods first, and only then the rest.

Chapter 5 is entirely new. Read it straight after the data model material, because many of the data classes you meet are likely to be generated with class-building tools rather than written by hand line by line.

## Second idea: type hints are a map, not a safeguard

The second edition devotes two new chapters, 8 and 15, to type hints. For an FDE, their value is that you can understand a system before you run it.

Imagine a function in a client's SDK with the signature `def fetch(ids: list[str]) -> dict[str, Order] | None`. That single line tells you what goes in, what comes out, and that you must handle the `None` case. Without hints, you would be setting breakpoints and guessing.

But there is a point Ramalho stresses on Thoughtworks' technology podcast: annotations have no effect at runtime; it is tools such as mypy that use them to catch errors in source code. The map is only trustworthy if someone checks it regularly.

**Key point:** You read client code fastest when you understand the language the way its authors think in it.

## Third idea: choose a concurrency model before you write

Chapter 19, on concurrency models, is new and sits in the most heavily rewritten part of the book. It deserves a careful read because it gives you the vocabulary to tell threads, processes and async apart before you touch any code.

Picture an integration job that has to call 200 of a client's endpoints, each call taking about 0.5 seconds, almost all of it waiting on the network. Run sequentially, that is 200 × 0.5 = 100 seconds, while the CPU sits nearly idle. This is an I/O-bound task, so parallelising the waiting is the right approach.

If the client's SDK is a synchronous library, a thread pool with 20 workers requires the fewest code changes: the 200 calls split into 10 rounds, bringing the total down to about 5 seconds. If the whole chain already has an async client, asyncio with a limit of 20 concurrent requests gives a similar result. And if the slow part is CPU-heavy data parsing, neither approach will save you.

## Three traps when taking the book into a real project

The first trap is copying the book's asyncio patterns wholesale into client code. The ACCU reviewer considers the asynchronous programming chapters outdated, so take the thinking from chapter 19, and check specific APIs against current Python documentation before using them.

The second trap is trusting hints in a repo that has never run mypy. Because annotations have no runtime effect, hints may have drifted from reality long ago without anyone noticing.

On day one, ask the client's team whether CI runs a type checker. If it does not, run mypy locally and treat the error count as a measure of how far the map can be trusted.

The third trap is parallelising before measuring. Before writing the first line of concurrent code, measure how long a single call takes and set a limit on the number of requests, so your job does not overload the client's own API.

## Turn reading into evidence on your CV

The official example code lives in the `fluentpython/example-code-2e` repo on GitHub, and fluentpython.com is the companion site for the second edition, with additional articles in its extra section.

The most effective way to read is to refactor as you go. Pick an old Python project of your own, convert hand-written data classes to data classes, add type hints and have mypy run in CI. On a CV, one line stating what you did, with a link to the commit, is far more convincing than the words "proficient in Python".

Memorising syntax is not the goal. The goal is to open an unfamiliar repo and understand it fast enough for the client's team to trust you, and the chapters above are the shortest route to practising exactly that skill.

**Try this week:**

- Clone the fluentpython/example-code-2e repo, run the examples for chapters 1 and 5, then write your own class with __len__ and __getitem__.
- Take an old Python module of yours that has no type hints, add hints following chapter 8 and run it through mypy.
- Read one article on fluentpython.com/extra and note one thing you had misunderstood about Python.

## Sources

- [GitHub - fluentpython/example-code-2e](https://github.com/fluentpython/example-code-2e)

- [example-code-2e/README.md at master · fluentpython/example-code-2e](https://github.com/fluentpython/example-code-2e/blob/master/README.md)

- [Fluent Python, Second Edition – Extras](https://www.fluentpython.com/extra/)

- [fluent python 2nd edition – Thoughtworks](https://www.thoughtworks.com/insights/books/fluent-python-2nd-edition)

- [Thoughtworks Technology Podcast – The future of Python (Luciano Ramalho)](https://www.thoughtworks.com/insights/podcasts/technology-podcasts/future-python)

- [REVIEW - Fluent Python (2e)](https://accu.org/bookreviews/2023/wiesenhuetter_2005/)

- [Book recommendation: Fluent Python (2nd Edition)](https://hamatti.org/posts/book-recommendation-fluent-python/)
