The world's best-selling Python introduction: the basics, then three real projects (game, data viz, web).
Why this book
"Where do I start?" is the question I get asked most often, and it's the hardest one. Not because resources are scarce: because there are too many, and most of them drown the beginner in everything they don't need to know yet. Python Crash Course is the answer the market settled on: more than a million copies in print, translated into over ten languages, the best-selling Python introduction in the world.
I read it wearing two hats. The developer who wants a reliable recommendation to hand out. And someone who spends his evenings building courses for beginners: Eric Matthes taught high school math and science for 25 years, slipping Python classes into the curriculum whenever he could find a slot. This book is what 25 years of classroom experience produce when you compress them into 552 pages. That's worth studying.
The ideas that stick
The book runs 552 pages in two halves: eleven chapters of basics, then three complete projects to pick from. Here is what stays once it's closed.
1A "well-curated" course, not an encyclopedia
A beginner's book should be judged by what it leaves out. Matthes says it plainly in his preface: "my main goal in revising the book is to keep it a well-curated introductory Python course". Concretely, every edition cuts as much as it adds. The 3rd:
- replaces
unittestwith pytest (the testing tool that became the standard); - swaps the old
open()for pathlib (the modern way to handle files); - drops Heroku for Platform.sh;
- sets the beginner up on VS Code.
No dict comprehensions, no home-made decorators, no metaclasses: not because they're useless, but because it's not the day. That selection is the real pedagogical work: deciding the order and the subset, and owning the cuts at every edition.
2Variables are labels, not boxes
Almost every beginner course explains that a variable is "a box that holds a value". Matthes corrects it as early as page 18: "this idea can be helpful the first few times you use a variable, but it isn't an accurate way to describe how variables are represented internally in Python. It's much better to think of variables as labels that you can assign to values."
The difference looks cosmetic; it's fundamental. A box contains ITS value, so assignment should copy. In Python, assignment sticks one more label onto the same object. The day two variables mysteriously "share" a list (you change one, the other changes too), the box model collapses and the label model explains everything.
Giving the right mental model in chapter 2, before the trap is even possible, is what separates a designed course from a recited one.
3Errors are made on purpose
Chapter 1, exercise 1-2: deliberately put a typo in hello_world.py and watch what happens. Breaking the program is an official exercise.
Matthes then causes his own errors in front of you: he types mesage instead of message and walks through the traceback line by line, pointing out along the way that Python now suggests the fix. And he defuses the shame: "many programming errors are simple, single-character typos in one line of a program. If you find yourself spending a long time searching for one of these errors, know that you're in good company" (p. 18).
The implicit lesson holds for any language: an error isn't a failure, it's the standard output of the trade, and reading a traceback is a skill you can teach, not a gift.
Traceback (most recent call last):
File "hello_world.py", line 2, in <module>
print(mesage)
^^^^^^
NameError: name 'mesage' is not defined. Did you mean: 'message'?
4"Now is better than never"
At the end of chapter 2, Matthes has you type import this and comments a few lines of the Zen of Python. The one he saves for last is a learning program all by itself: "Now is better than never. You could spend the rest of your life learning all the intricacies of Python and of programming in general, but then you'd never complete any projects" (p. 31).
The whole book flows from that line: you don't learn the language to know it, you learn just enough to build something that works, and you fill in the gaps along the way. It's anti-perfectionism turned into a method, and it's exactly the reflex missing in beginners who collect tutorials without ever finishing anything.
5The plan is prose, the refactoring happens en route
Chapter 12 opens the first project (a Space-Invaders-style game) with a project management lesson in disguise. First: "when you're building a large project, it's important to prepare a plan before you begin to write code" (p. 228). That plan is not a forty-page spec: it's one paragraph of prose describing the game.
Then the first increment is tiny: an empty Pygame window that opens and closes. After that, every round runs the same loop: add one small feature, check it on screen, and refactor BEFORE adding the next one.
Matthes says it in so many words: "in large projects, you'll often refactor code you've written before adding more code" (p. 237), and he owns the consequence: "you start out writing your code as simply as possible, and then refactor it as your project becomes more complex" (p. 238). Refactoring is not the end-of-project cleanup: it's a step in every single loop.
6Testing is a beginner skill
The book's most unexpected choice: chapter 11, still in the "basics" half, teaches pytest. Not as an option, not in an appendix: between files and the first project. The argument lands as early as page 2: "testing your code is one of the first skills that will help you transition from beginner to intermediate programmer".
The demonstration is crystal clear: a function that formats names (Janis Joplin comes out as "Janis Joplin"), a passing test, then a middle name gets added and the test breaks. The rule that follows deserves engraving: "so when a test fails, don't change the test" (p. 215): fix the code, because other calls break exactly like the test did.
And the rare honesty: "don't aim for full coverage in early projects unless you have a specific reason to do so" (p. 223). Test early, yes; the coverage dogma, no.
from name_function import get_formatted_name
def test_first_last_name():
formatted_name = get_formatted_name('janis', 'joplin')
assert formatted_name == 'Janis Joplin'
7OOP is for modeling, not reciting
The classes chapter fits in one sentence: "think of a class as a set of instructions for how to make an instance" (p. 159). The running example is deliberately mundane: a Dog class with a name and an age, then a Car extended into an ElectricCar, whose battery becomes a separate Battery class.
He names the technique, composition: the car doesn't store battery details itself, it holds a Battery object that handles them.
class Battery: # a separate class: its only job, the battery
def __init__(self, kwh=75):
self.kwh = kwh
def range(self):
return self.kwh * 5 # km
class ElectricCar(Car):
def __init__(self, make):
super().__init__(make)
self.battery = Battery() # the car HAS-A battery
my_tesla.battery.range() # delegate to the object that knows
The day the battery gets more complex (charging, degradation, models), it all stays inside Battery; the car knows nothing about it. But the real lesson comes when Matthes makes you think about what you're modeling: "you're thinking not about Python, but about how to represent the real world in code" (p. 173).
And again, the curation: no @property, no class methods, no special methods beyond __init__. Model first; the advanced syntax can wait.
8Three projects, three doors into the trade
The second half of the book is three complete, independent projects, in any order you like:
- a game (Alien Invasion, with Pygame);
- data visualization (matplotlib then Plotly);
- a web application (a learning journal in Django).
Three projects = three possible careers, and the reader picks a door. The detail that changes everything: the data is real. The weather comes from NOAA records for Sitka, Alaska, and Death Valley; the earthquakes from the USGS real-time feed; the most-starred repositories from the GitHub API. And the Django project goes all the way: Bootstrap, user accounts, and a real deployment on Platform.sh, DEBUG=False included. A beginner's book that ends with your app online, reachable by the whole world, is still the exception.
Three things I didn't know
- Matthes learned to program as a child, on a bare motherboard hooked to a cathode-ray tube in his father's basement: his dad worked at Digital Equipment Corporation, one of the pioneers of modern computing. His first program was a number-guessing game.
- Modern Python tracebacks do the diagnosis for you: type
mesageinstead ofmessageand Python answers "Did you mean: 'message'?". Matthes turns this into a teaching point from chapter 2 on: reading the error is, more and more often, enough to fix it. - The book has an official GitHub repo (pcc_3e): all the code for the twenty chapters, the exercise solutions and cheat sheets, maintained by the author. The "continuously updated third edition" actually exists.
My take, honestly
This book does one single thing, and does it better than anyone: turning someone who has never coded into someone who has finished a real project. The pedagogy is remarkably clean: every notion arrives with the simplest possible example, immediate exercises, and the traps are defused before they're ever met. Writing my own courses, I found in it just about every lesson it took me years to learn, already applied, without noise.
Let's be honest about what it isn't. If you already know how to program, you will be bored: two full chapters on lists is the pace of a first book, not of an express conversion from JavaScript. And it almost never explains how Python works under the hood: it gives you the right move, rarely the mechanics underneath. That's a deliberate choice, the right one for its audience, but you should know it: you come out able to build, not to shine in an interview about the memory model.
Hence my rule: Python Crash Course is the first book; Fluent Python (already in this library) is the thirteenth. One teaches you to write Python that works, the other to speak the Python of natives. Their ratings don't compare: you don't grade a front door the way you grade a cathedral.
Odilon
Still relevant in 2026?
For this book the question reads differently: is learning to code still worth it when AI writes the code? Answer: Matthes' method is precisely the one you need to work with an AI. Describe what you want in clear prose, ask for the smallest increment that runs, check it, refactor before adding: that's his loop from idea 5, and it's word for word how you drive a coding assistant. As for reading a traceback and judging what's too big or badly split, that's exactly what separates the person who drives the AI from the person who endures it. The 3rd edition (2023) is current: pytest, pathlib, f-strings, VS Code. Only the last project will age: Django 4.1 and Platform.sh are dated choices by nature, and the author maintains the fixes on the official repo.
Who is it for?
Read it if
- You've never programmed and you want ONE book, not a list of 40 resources
- You're switching careers and need solid basics plus three projects to show
- You know the syntax but you've never finished a complete project
- You teach or build learning content: it's a textbook case of course design
Skip it if
- You already write Python daily: go straight to Fluent Python
- You come from another language and just need the syntax: the docs and a good cheat sheet will do
- You want the internals (memory, the GIL, typing): that's not what this is
Going further
This book's method can be practiced in my free courses: the step-by-step basics in the Python course, the plan → increment → refactor loop in Coding with AI, and chapter 11 continues in the testing course. The complete code for all twenty chapters, the solutions and the cheat sheets live on the author's official repository. And if you're still hesitating on the first step: Where to start.
Comments (0)