Written for people first: readability, indentation and great Python code

October 21, 2026 · 19 min read

Guido van Rossum describes programs as recipes written for two audiences and explains why readability matters, Chris Lattner weighs Python's strengths and the indentation debate while building Mojo on top of it, and The Hitchhiker's Guide to Python gives whole sections to writing and reading great code. Together they show why the people who build and teach Python treat code as something humans must read, not only something a machine must run.

The Short Version

Guido van Rossum, who started Python, says a program has two audiences at once: the computer that runs it and the programmers who must read, debug and improve it, which is why Python's style guide holds that readability counts and why the language makes indentation part of its grammar [1]. Chris Lattner, who is building Mojo as a superset of Python, defends that same indentation on practical grounds (it removes clutter, avoids bugs where the layout lies about the logic, and matches what automatic formatters do to brace languages anyway) and keeps it in Mojo while adding the speed Python lacks [2]. The Hitchhiker's Guide to Python, by Kenneth Reitz and Tanya Schlusser, turns the same values into working habits: follow PEP 8 and the Zen of Python, write code that is clear and direct for human readers, and get better by reading well-made open-source projects the way writers read good writing [3]. The book's underlying attitude, like van Rossum's point that software is built by teams and never right the first time, is that you should build everything as if other people will use it, because sooner or later they will [1][3].

Table of contents

What They Said

Guido van Rossum: a program is a recipe with two audiences

Van Rossum, Python's creator and "emeritus BDFL," now at Microsoft, starts from the basics in his conversation with Lex Fridman, which frames the explanation for an imaginary fisherman and a seasoned Silicon Valley programmer on the same boat [1]. A programming language, he explains, is a list of instructions, like a cookbook recipe for a sandwich, that has to be completely unambiguous because computers lack human context [1]. In his words, "computers are very dumb, and they need very precise instructions because they don't have much context" [1]. Fridman observes that in human languages "ambiguity is a feature, not a bug," and van Rossum notes that for lawyers it certainly is [1].

That precision is only half the story. When Fridman brings up PEP 8, Python's style guide, and its idea that code readability counts, van Rossum answers, "So this recipe should be readable. That's a thing between programmers" [1]. What has emerged since the early days of computing, he says, "is that software is a very social activity. A software developer is not a mad scientist who sits alone in his lab writing brilliant code" [1]. Instead, "A software is developed by teams of people" [1].

Why a program is not like a cookbook

Van Rossum draws a careful distinction. A cookbook author writes a recipe once, it is printed in 100,000 copies, and many people in their kitchens try to follow it, so the author's goal is to make it clear to the human reader [1]. A program is different: "When you're writing a computer program, you have two audiences at once. It needs to tell the computer what to do" [1]. But it also matters that the program "is readable by other programmers," because software, unlike a typical cherry pie recipe, "is so complex that you don't get all of it right at once" [1].

That complexity is why debugging exists, which he describes as "trying to figure out why your code doesn't run the way you thought it should run" [1]. The errors range "from a typo to a wrong choice of algorithm to building something that does what you tell it to do but that's not useful" [1]. The conversation describes software as a social endeavor in which people keep improving the recipe, whether as a group or as a lone author returning to something written a year earlier [1].

Even a lone programmer benefits from conventions. Van Rossum says that "even the mad scientist coding alone in his lab would be sort of wise to adopt conventions on how to format the instructions that he gives to the computer" [1].

Indentation as the layout of a good cookbook

Asked about Python's distinctive indentation, van Rossum goes back to the kitchen. "Spaces are important for readability of any kind of text," he says [1]. Take a cookbook recipe, remove the bullets and markup and crunch the text together, and a cook trying to work out the ingredients, the steps and where one step ends and the next begins is "going to have a hard time if it's if it just one solid block of text" [1]. A good cookbook, by contrast, starts each recipe on its own page, lists the ingredients first and uses a standard notation and shortcuts [1].

Indentation plays that role in code. Python's four spaces were a compromise shaped by old conventions and 1980s screen widths [1]. Google's style guide uses two spaces per block, and van Rossum says that if you're not used to that, "it's harder to at the glance understand the code because the high level structure is determined by the indentation" [1]. Classic Unix code indented by a whole eight-space tab stop has the opposite problem: "To me, that looks weird because you have three indent levels. You've got no room left" [1].

What makes Python different is that indentation is part of the language rather than a style recommendation [1]. In some languages, "The code compiles even without any indentation"; in Python, "indentations are fundamental part of the language" [1]. The number of spaces is not fixed, and you could use two, six or twelve, "But sort of everything that belongs to the same block needs to be indented the same way" [1]. He adds that programmers in other languages, and their IDEs, are just as strict in practice [1].

Would he choose braces today?

Van Rossum answers with context. Almost every other major language uses curly braces, so Python is the odd one out, and it could never switch now because braces already mean dictionaries [1]. But in a green field he would still argue for indentation, because it reduces clutter, "frees up a pair of matched brackets of which there are never enough in the world for other purposes", and lets beginners spend less time fighting syntax such as misplaced semicolons [1]. That matters because a first programming course already has to cover algorithms, data structures, loops, functions, recursion and more [1].

Readability beyond layout: names, symbols and types

Van Rossum's concern for the reader shows up in other parts of the conversation too. Explaining why shells, Perl and PHP put a dollar sign before variables, he says it began as a trivially simple way for early script processors to tell variables from file names, but that "It also helps even then it also helps the human author and the human reader of the script to quickly see" that a name 20 lines down is one of the script's parameters [1].

When he explains why concurrent code is hard, he describes what reading code demands of a person. "You need your whole brain when you're reading a piece of code," he says, keeping track of what is in each variable [1]. His example loads one count into variable A and another into B, and he adds, "Hopefully you have better names" [1]. Concurrency makes it worse, because human brains are not built to track several things at once, and when two pieces of code share a variable, every possible ordering of operations has to be anticipated [1].

On types, he explains that Python's type hints are not checked when the code runs; a separate static type checker reads the code and flags inconsistencies, and the hints are especially popular at large companies with huge codebases [1]. He would recommend TypeScript over plain JavaScript because strict typing helps you keep your head straight about what your code does [1]. Even his use of GitHub Copilot rewards clear naming: its suggestions often complete a whole line or a five-to-ten-line function if he names the function well [1].

Simplicity first, complexity only when needed

Van Rossum's account of how Python 3.11 became 10 to 60 percent faster shows the same priorities from another angle. When he started Python, he wanted something working in about three months, so he wrote the code as simply as possible [1]. He illustrates the trade-off with prime numbers: a naive check tries every divisor, while smarter versions stop at the square root, skip even numbers and check only previous primes, gaining speed at the cost of complexity [1]. Thirty years of simple code left low-hanging fruit, and the 3.11 speedup came mostly from an adaptive specializing interpreter that preserves the dynamic typing that makes Python friendly to beginners [1].

His advice to learners stays practical: "Find something you actually want to do with it" [1]. He mentions a blog post arguing the goal should be to "learn Python in 10 years," and notes that memorizing syntax doesn't make you a coder [1].

Chris Lattner: keeping Python's readability while fixing its speed

Chris Lattner, creator of LLVM, Clang and Swift, talks with Lex Fridman about Mojo, a new language designed to be a superset of Python with the performance of C and C++ [2]. His view of Python is admiring and specific, and his defense of its indentation is one of the clearest arguments in these sources.

What Python gets right

Fridman lists what he loves about Python: it reads almost like English, it is condensed, and there is a package for everything [2]. Lattner adds that Python is "the universal connector" that lets people compose large systems [2]. Later he lists more virtues: a huge package ecosystem, very low startup and compile time compared with languages like Java, elegant integration with notebooks, a simple object representation that makes it the glue of computing, and dynamic metaprogramming that enables beautiful APIs [2]. Python owns machine learning and is taught everywhere; his own kids learned it in school [2]. Its main weakness, in his view, is that it is slow, and his verdict is that Python is not broken, just "not done yet" [2].

The indentation debate, argued rationally

On the perennial argument over indentation versus curly braces, Lattner defends indentation with three practical points [2]. First, curly-brace languages end up run through automatic formatters anyway, so in practice their code is indented consistently regardless [2]. Second, misleading indentation, where the layout suggests one structure and the braces say another, has caused notorious bugs [2]. Third, having one notion of grouping eliminates clutter and a whole design space of optional-brace rules [2].

He admits he likes poking the bear, and jokes that proposals to add braces to Mojo get a polite no [2]. Mojo uses indentation rather than curly braces [2].

Meeting programmers where they are

Lattner's broader philosophy is that the enemy is complexity, and that the goal is to meet programmers where they are rather than force them to rewrite their code [2]. He tells a story from building Clang around 2006: he intended a pure, standards-compliant C parser, but real-world headers such as stdio.h depended on GCC's quirks, and he realized it is far easier for engineers to implement long-tail compatibility than to persuade all C programmers to rewrite their code [2]. The same reasoning drives Mojo's superset strategy, and he politely declines to call Mojo Python 4.0 because of the trauma of the Python 3 transition [2].

That respect for existing code and existing habits shows in Mojo's design choices. The def keyword works exactly as in Python, while fn is a stricter mode requiring declared variables, which appeals to systems programmers [2]. Types can be adopted progressively, and Lattner rejects the idea that untyped Python is a "guilty pleasure" that must be rewritten for serious work: prototypers should not feel pressured, while large teams may adopt house rules requiring types [2]. He notes that Python's own type hints are ignored by the interpreter and interpreted differently by competing checker tools, whereas in Mojo a declared type is enforced by the compiler [2].

Fewer surprises for the people reading and changing code

Several of Mojo's features aim at bugs that come from code behaving differently than a reader would expect. Value semantics make collections behave as if you get a logical copy, which prevents bugs like a database class holding onto a record that a coworker later modifies [2]. Python programmers usually resort to defensive copies, and PyTorch users must remember to clone tensors in the right place [2]. His guiding principle is to take magic out of the compiler and put it in libraries, so that user-defined types are never second-class citizens [2].

Lattner also intends to resist syntactic sugar, which he says became addictive in the Swift community, and to hold design reviews with the broader Python community [2]. He sees programming languages, like English, as an exchange format [2]. His advice to young people is to build things rather than memorize books, and "if everybody's going left sometimes it's pretty cool to go right" [2].

Get new summaries by email

The GIST of every new summary in your inbox, daily or weekly. Free, and you can unsubscribe any time.

The Hitchhiker's Guide to Python: readability as a community habit

The Hitchhiker's Guide to Python, by Kenneth Reitz and Tanya Schlusser, published by O'Reilly in 2016 with the subtitle Best Practices for Development, is not a tutorial [3]. Its Preface says it "is not intended to teach you the Python language" but is "an (opinionated) insider's guide to our community's favorite tools and best practices" [3]. It grew out of a free, open-source website, a "living, breathing guide" that the Python community writes together, and the publisher credits over a hundred community members as contributors [3]. Reitz is best known as the creator of the Requests library, and Schlusser is a consultant with more than two decades of experience across half a dozen languages [3].

Why the book exists

The worry behind the book is that a language built on simplicity can lose its shared habits as it grows [3]. The publisher's description puts it this way: "More than any other language, Python was created with the philosophy of simplicity and parsimony," and "With popularity comes diversity—and possibly dilution" [3]. The Preface opens with a parody of Douglas Adams: "Python is big. Really big. You just won't believe how vastly hugely mind-bogglingly big it is" [3]. The book's answer is to have opinions, recommending tools rather than listing every option evenly, and to be, in the publisher's words, "light on reusable code and heavier on design philosophy" [3]. It promises to take the "journeyman Pythonista" toward real expertise [3].

Writing great code

Part II is the heart of the book, and its first chapter, Writing Great Code, starts with style [3]. PEP 8 is the community's style guide, the shared set of conventions that makes one person's Python look like another's [3]. PEP 20, the Zen of Python, sets out the values underneath, in aphorisms by Tim Peters such as "explicit is better than implicit" and "readability counts" [3]. The authors treat these not as decoration but as the test of whether code is Pythonic: clear, direct and written to be read by humans [3].

From there the chapter gets concrete, covering the idioms experienced developers reach for and classic traps such as mutable default arguments and late-binding closures [3]. It explains how to structure a project, from the repository layout to modules and packages, on the principle that structure is the key to code people can navigate [3]. It insists that code is not finished when it runs: a project needs tests, documentation, sensible logging and a deliberate choice of open-source license, built as if other people will use it, because sooner or later they will [3].

Reading great code

The fifth chapter holds the book's most distinctive idea: you become a better programmer the way writers become better writers, by reading good work [3]. Instead of snippets written for the occasion, it walks through real, respected open-source projects, among them Reitz's own Requests and Tablib and the web framework Flask, pointing out their structure, style and design choices: short functions, clear names and modules used sensibly [3]. Requests is the showcase for what Reitz calls design "for humans," in which a library's interface is built around what a person naturally wants to do rather than around how the machinery works [3]. The lesson is a skill: learn to open an unfamiliar project, find your way around it, notice the patterns and carry them back into your own work [3]. The Preface suggests even casual Python users will get something from this chapter [3].

Shipping for the people who receive it

The same attention to the human on the other end runs through the chapter on packaging. Its organizing question is simple: who is receiving this [3]? If your audience is other developers, give them a package they can install; if it is end users who neither know nor care what Python is, give them a frozen application [3].

Where They Agree, and Where They Don't

Where they agree

Code is read by people, not only run by machines. Van Rossum says a program has two audiences at once and should be readable by other programmers [1]. The Hitchhiker's Guide treats code written to be read by humans as the test of whether it is Pythonic [3]. Lattner's stated goal is to meet programmers where they are rather than force them to rewrite their code, and his value semantics prevent bugs like a record changing because a coworker modified it [2].

Indentation is the right way to show structure. Van Rossum would still choose indentation in a green field [1], and Lattner keeps it in Mojo and turns down proposals for braces [2]. Both say it reduces clutter [1][2].

Shared conventions matter. Van Rossum says even a lone programmer would be wise to adopt formatting conventions, and traces the readability idea to PEP 8 [1]. The Hitchhiker's Guide describes PEP 8 as the shared conventions that make one person's Python look like another's [3]. Lattner points out that brace languages end up run through automatic formatters anyway [2].

Simplicity is worth protecting. Van Rossum wrote Python as simply as possible and added complexity only where speed demanded it [1]. Lattner names complexity as the enemy [2]. The Hitchhiker's Guide exists because a language built on simplicity risks dilution as it grows [3].

Types are optional, not mandatory. Van Rossum describes type hints as annotations checked by a separate tool rather than at runtime [1], and Lattner lets Mojo programmers adopt types progressively and says prototypers should not feel pressured [2].

Where they differ

Why indentation wins. Van Rossum's reasons center on the reader and the learner: indentation is like the layout of a good cookbook, it frees brackets for other uses, and it spares beginners syntax fights [1]. Lattner's reasons are more about correctness and consistency: misleading indentation has caused notorious bugs, formatters already enforce indentation in brace languages, and one notion of grouping removes a whole design space of rules [2]. The two lines of argument reach the same conclusion from different directions.

How settled the question is. Van Rossum answers in context: Python is the odd one out among major languages, and it could not switch even if it wanted to, because braces already mean dictionaries [1]. Lattner treats it with more relish, admitting he likes poking the bear [2].

What type hints should do. Van Rossum explains that Python does not use annotations to speed up the interpreter, partly because annotations sometimes contain "lies" and enforcing them would break many dynamic programs [1]. Lattner sees the fact that Python's type hints are ignored by the interpreter and read differently by competing tools as a limitation, and in Mojo a declared type is enforced [2]. Van Rossum's position protects existing dynamic code; Lattner's aims at performance and certainty for code that opts in.

What comes first: readability or speed. For van Rossum, simplicity came first and speed was added carefully decades later, keeping the dynamic typing that helps beginners [1]. Lattner starts from Python's slowness as its main weakness, and his project works backward from the limits of physics, while keeping Python's syntax so nobody has to rewrite their code [2].

The book's limits. The Hitchhiker's Guide is a snapshot of 2016, and some of its tool recommendations have aged [3]. Critics say it is shallow by design and adds little to the free website it came from, while fans call it a practical, no-fluff overview [3].

Why It Works

Computers need precision; people need context. Van Rossum explains that a program must be completely unambiguous because computers lack human context, but that its other audience, programmers, needs to understand it well enough to debug and improve it [1]. Readability is how one text serves both.

Software is never right the first time. Because programs are too complex to get right at once, they are debugged and improved continually, by teams or by their original author [1]. That ongoing work depends on other programmers being able to read the code [1].

Layout carries structure. In a recipe, layout tells a cook where one step ends and the next begins [1]. In code, "the high level structure is determined by the indentation," so an unfamiliar indentation width makes code harder to understand at a glance [1]. When the indentation is the grouping, as in Python, the layout cannot disagree with the logic, which is the source of the misleading-indentation bugs Lattner describes in brace languages [2].

Reading code uses your whole working mind. Van Rossum says reading a piece of code takes your whole brain, keeping track of what each variable holds, which is why better names help and why concurrency, where several things change at once, is so hard [1].

Fewer surprises mean fewer bugs. Lattner's value semantics keep a collection from changing under you when a coworker modifies the original, removing the need for defensive copies [2].

Shared conventions let anyone read anyone's code. PEP 8 makes one person's Python look like another's, and good projects show their structure through short functions, clear names and sensible modules [3]. Reading such projects builds the pattern recognition that carries back into your own work, the way writers learn from good writing [3].

Where It Applies, and Where It Doesn't

It applies most where code lives a long time and changes hands. Van Rossum's argument rests on teams and on code being improved over time [1], and he notes that type hints are especially popular at large companies with huge codebases [1]. Lattner says large teams may adopt house rules requiring types [2].

It applies even when you work alone. Van Rossum says the mad scientist alone in his lab would still be wise to adopt conventions on how to format his code [1].

Prototyping gets more freedom. Lattner says prototypers should not feel pressured to add types, rejecting the idea that untyped code is a guilty pleasure [2]. Van Rossum likewise keeps type hints optional and outside the runtime [1].

Indentation is not a magic number. Python requires consistency within a block, not four spaces specifically; two, six or twelve also work [1]. The four-space convention is a compromise shaped by history and screen widths, not a law [1].

Readability is not the only goal. Lattner's work exists because Python's readability came with slowness, and he wants both [2]. Van Rossum's own speedups added complexity to the interpreter for the sake of performance, while preserving the dynamic typing that makes Python friendly to beginners [1].

Some advice has a shelf life. The Hitchhiker's Guide's tool recommendations date from 2016, and its Python 2 versus 3 discussion has answered itself [3].

What To Do With It

  1. Write for two audiences. Before you call code finished, ask whether another programmer, or you later on, could debug and improve it, not only whether the computer runs it [1].

  2. Follow PEP 8 and read the Zen of Python. Use the community style guide so your code looks like other people's Python, and take lines such as "readability counts" and "explicit is better than implicit" as tests of your own code [3].

  3. Indent consistently. Keep everything in a block at the same indentation, and stick with the common four-space convention so others can read the structure at a glance [1].

  4. Name things for the reader. Choose names that tell the reader what a variable holds, so they don't have to keep A and B in their head [1]. Clear function names also help tools like Copilot suggest the right code [1].

  5. Add types where the codebase is large or shared. Use type hints and a static checker in larger projects, and adopt house rules for types on big teams, while leaving quick prototypes free [1][2].

  6. Avoid the classic traps. Learn the common Python pitfalls, such as mutable default arguments and late-binding closures, and the idioms experienced developers use instead [3].

  7. Structure the project so people can navigate it. Lay out the repository, modules and packages deliberately, and add tests, documentation, logging and a license as if strangers will depend on your code [3].

  8. Read good code on purpose. Open a well-regarded project such as Requests or Flask, find your way around it, and note its short functions, clear names and sensible modules, then use those patterns yourself [3].

  9. Keep it simple until performance demands otherwise. Start with the simplest code that works, as van Rossum did with Python itself, and add complexity only where speed truly requires it [1].

  10. Learn by building. Pick a project you actually want to do rather than memorizing syntax or books [1][2].

Sources

  1. Guido van Rossum on Python 3.11's Speedup, Type Hints, the GIL and the Future of Programming · Lex Fridman Podcast
  2. Chris Lattner on Mojo, Modular and the Future of Programming and AI · Lex Fridman Podcast
  3. The Hitchhiker's Guide to Python ·