Why Python’s whitespace rule is right

In Language design, Python on October 18, 2011 by Matt Giuca Tagged: , , ,

Python is famous among programming languages for its fairly unique syntax: rather than being delimited by curly braces or “begin/end” keywords, blocks are delimited by indentation. Indenting a line is like adding an opening curly brace, and de-denting is like a closing curly brace. When people criticise Python, it is usually the first complaint: “why would I want to use a language which requires me to indent code?” Indeed, while programmers are very used to indenting their code, they are very un-used to being forced to do so, and I can understand why they may take it as an insult that a language tells them how to write code. I don’t usually like to get into syntax arguments, because I find them very superficial — it is much more important to discuss the semantics of a language than its syntax. But this is such a common argument among Python detractors, I wanted to address it. Python is right, and it’s just about the only language that is.

I think the rub is that programmers like to think of languages as a tool, and tools should be as flexible as possible. I think in general it is a good principle for programming languages not to enforce conventions. Languages that do tend to annoy people who don’t subscribe to the same conventions. For example, the Go programming language enforces the “One True Brace Style” — every opening curly brace must appear on the same line as the function header or control statement. This irritates me because that’s not my preferred convention. But the indentation convention is so universal that it is considered bad programming practice to not indent in all cases. (There is disagreement over tabs vs spaces, the number of spaces, etc, but we all agree that indentation is good.) There is not a single situation in any country, in any programming language, or at any skill level, in which is it acceptable to not indent your code the way Python requires it. Therefore, it is technically redundant to have a language that is not whitespace-sensitive. Any language that is not whitespace-sensitive requires (by universal convention) that programmers communicate the scoping of the code in two distinct manners for every single line of code: braces (or begin/end) and indentation. You are required to make sure that these two things match up, and if you don’t, then you have a program that doesn’t work the way it looks like it works, and the compiler isn’t going to tell you.

There are two solutions to this problem. 1: Make the compiler tell you. Force the programmer to indent and put in curly braces, and have the compiler check the indentation and give either a warning or error if they don’t match up. Now you’ve solved the problem of accidentally getting it wrong, but now what is the point of requiring curly braces at all? The programmer would just be doing extra work to please the compiler. We may as well go with 2: take out the curly braces and just have the compiler determine the blocks based on indentation.

When you really analyse it, Python’s whitespace sensitivity is actually the only logical choice for a programming language, because you only communicate your intent one way, and that intent is read the same way by humans and computers. The only reason to use a whitespace-insensitive language is that that’s the way we’ve always done things, and that’s never a good reason. That is why my programming language, Mars, has the same indentation rule as Python.

* * *

An interesting aside: there is a related syntax rule in Python which doesn’t seem quite so logical: you are required to place a colon at the end of any line preceding an indent. I haven’t fully tested this, but I’m pretty sure there is no technical reason for that (the parser could still work unambiguously without that colon), and it doesn’t seem to add much to the readability either. I slavishly followed this rule in Mars too, because as a Python programmer it “feels right” to me. But perhaps it would be better to drop it.

77 Responses to “Why Python’s whitespace rule is right”

  1. The colon rule probably helps editors – after a colon and a newline, they know you _must_ indent (and will do so for you typically), without having to pay special attention to keywords.

    Also more importantly, it means you have the exact same syntax for a single-line conditional:

    if foo:

    naturally condenses (if you wish) to

    if foo: continue

    • the comment field ate my indentation, but you know what I mean…

    • Good point. The editor isn’t so important since I’m sure an editor could detect “Line beginning with def/if/while/for/etc and not containing a colon”. But the consistency is a good point.

  2. (I agree with you wholeheartedly.) No, the colon isn’t necessary. For example, Haskell has significant whitespace and no colon.

  3. I cannot imagine how a language that breaks if you indent wrong, could be considered not only a logical choice, but “the only logical choice”. It’s no doubt perfectly logical for the computer itself, and perhaps it might be for another species, but not for this species.

    Sometimes, the road less traveled is less traveled for a reason.

    • Could you explain why it is not for this species? Or what the “reason” is that you think the road is less traveled? I thought I did a pretty good job of explaining why it is perfect for this species in the post: this very species has near universal coding standards that say you must indent your code. So since you are indenting your code anyway, why not make sure you are indenting correctly?

  4. @Matt, consider the difference between Python’s

    if x:
    if y:

    and C’s

    if (x) {
    if (y) {
    } else {

    In the C case, the meaning is unambiguous; in the Python case, only the indenta— I’m sorry, what’s that? WordPress ate my indentation? Well, crap. You know what I *meant* to write, though… don’t you? I mean, source code is meant for humans to read, so it would be *pretty dumb* if you couldn’t paste source code into a blog comment without breaking it…

    • It’s true, but I consider this to be a deficiency of WordPress, not Python. While it would be less common to do so, I could write a blogging tool that strips out curly braces, and then C code would break. I consider “readability” and “looking like it does what it actually does” to be more important design goals for a programming language than “will the code break if pasted into random website X?”

      • Have you ever tried to paste C++ code using templates (or Java using generics) in a comment field that strips HTML tags?

    • BTW: that is a on liner:
      foo() if x and y else bar()

      • Huh? That is not equivalent. If x is True and y is False, neither foo nor bar should be called, but your one-liner calls bar. You would need `foo() if x and y else (bar() if not x else None)`.

  5. Sorry for commenting your post so lately, but I couldn’t resist 🙂

    I first saw whitespace delimited code in Haskell – what a crazy language, and good one too 🙂

    I am working with C# for almost 10 years now. I can only say the more I work with C#, the more I hate the braces. It is such a waste of time. In company where I work we had tools (FxCop, StyleCop) that enforced us to comply to company standards. Which is OK, of course, but then I noticed something, there was that strange rule in some of these tools that enforces you to begin every block with new line and also you needed to indent that block! So, at the end, there is that rule which is forcing you to do the same thing which Python enforces you but with additional braces, which you must maintain manually (or buy some 3rd party tool). You cannot checkin (commit) your code unless you fix it. It is same with companies which don’t have automated verification, at the end if you all agreed on some rules, why it is OK to break them down? There is only one reasonable answer to that – it is not OK, it must be automated – is it done by compiler or is it done by interpreter or any other 3rd party tool it doesn’t matter, it must be done by machines.

    And yes, whitespace is a piece of the program itself, we are already using it as input information for our eyes, why is so bad if we use the same information to feed the compiler/interpreter?

  6. Python’s indentation rule makes it harder to do code generation. In a language like this you need to provide a alternative mode for the sake of code generation (see what’s available in Haskell). In Python we do not have this, which really sucks a lot.

    • I’ll admit it’s a little harder: it means your code generator has to keep track of the indentation level at all times, and every time it inserts a newline, to insert that many spaces/tabs. But that’s a fairly trivial task compared to all the other things you have to be aware of when writing a code generator, for any language. I don’t think this is a big issue, especially since programming languages should be designed primarily for people to write, not computers.

      Haskell’s whitespace rule is much more complicated than Python’s, and yes, it would be much harder to write a code generator to whitespace-delimited-Haskell than Python, so it’s not really comparable (i.e., it’s good that Haskell provides a brace-delimited mode; Python doesn’t really need one).

    • To do code generation in Python, just do:
      ‘\t’ * indentLevel+statement

      IMO I think though you should use Hy for code generation, not the Python AST or strings though…

  7. Having worked with braceless and braced programming in YAML, JSON, Haskell, Java, HTML, HAML, Ruby, Python, XML, etc…

    You’re dead wrong about this: “The only reason to use a whitespace-insensitive language is that that’s the way we’ve always done things”

    No, the reason I love braces in my code is that I can press one key combo and automatically reformat my code while being absolutely sure that I have not changed its meaning. This is a good thing. It means that I don’t have to count spaces. I don’t have to worry about mixed tabs and spaces. I can bang out a few expressions on one line, hit a key combo, and have perfectly readable code without constantly wasting mental resources on meeting lame formatting standards.

    • I don’t follow this argument. Let’s trace back to my original point: with braces, there are *two* separate representations of the code structure: one machine-readable and one human-readable. If you don’t make sure they are exactly in agreement, then humans will most likely misunderstand your code. Whereas with whitespace-sensitivity, there is only one representation of the code structure, which both the machine and human can read and agree upon.

      Your point seems to be that you have a tool that takes the machine-readable representation and ensures the human-readable one matches. That’s great (I, too, use this tool — although it didn’t exist when I wrote this blog post in 2011 and I don’t know of any that did). But if you were using a whitespace-sensitive language, you wouldn’t need that tool at all, because the human-readable representation *always* matches the machine-readable one! “X is better than Y because X can achieve the same benefits of Y with additional tooling” is not an argument in favour of X.

      You should not be “counting spaces” — your eyes do that for you (you only have to observe what is more indented than what). You should *never* be mixing tabs and spaces, in any language, so that is a non-issue (and you will find that, while crappy C code mixes tabs and spaces a lot, it almost never happens in even crappy Python code because the program would break, so Python fixes that issue too). My point is that you do not *need* to waste mental resources reformatting code in Python because any correct code *is* correctly formatted already!

  8. You are a stupid pencil neck idiot. You are like someone who accepts to be bent over a barrel and be rammed up the ass by a guy with a huge strap on and say, “it’s ok, he’s using a condom so I won’t catch anything from my other geek pals who think the same shit as me”.
    No, it’s not all right to be forced to use whitespace you moron. It takes away choice. Any language that takes away choice should be binned immediately. Same goes for breaking backwards compatibility in under 10yrs. Invisible characters for code marking… sheer stupidity…. and fools like you who accept this make it all possible for the great creators of these garbage to state they have a product.

    • Decided not to mark this hideously offensive comment as spam just so that I can argue against it.

      > No, it’s not all right to be forced to use whitespace you moron. It takes away choice.

      What a ridiculous argument. Anything that takes away choice should be binned? C doesn’t let me choose between using double quotes or single quotes for strings, so that’s out. Java prevents me from converting an int into a pointer and crashing the computer; what a nasty restriction! Ruby insists that my instructions are executed from top to bottom, and not bottom to top.

      Language design — or rather, any design of anything ever — is about carefully choosing restrictions for the user to try and increase the chance of a good outcome. My microwave won’t let me use it while the door is open, to avoid me radiating myself. Do you think that’s wrong because it’s “taking away choice”? As I carefully argued in this post, the designers of Python deliberately take away your choice to write a program that looks one way, and behaves another. If you don’t like it, well, you’re free to choose a different language. But that is, in my opinion, a helpful restriction.

      As for your attitude, grow the fuck up if you want to be taken seriously.

  9. Here’s why the golang creators apparently didn’t like it: (I’m not arguing either way, but I had heard a quote from them once)

  10. The problem is that that entire argument for pyhtonic whitespaces leans on the developers having to do manual indentation.
    That’s not the case with a state of the art editor. You set the braces and the code get’s formated for you. That’s zero time spend on indentation and perfect output.
    Python on the other hand frequently forces the programmer to manually deal with indentation.
    That’s because the right indentation level can’t be deduced from anything else.
    For example each and every time when I would add a closing bracket I have to manually deindent.
    So no time safed there. But things get worse from there.
    In particular for code refactoring where pieces get moved around the indentation has to be adjusted manually most of the time.
    And while that’s only mildly annoying for moving larger blocks which can be (manually) indented en block it’s a huge waste of time for all the little changes when adding an additional condition or loop.

    • While you’re certainly right that automatic formatting tools make brace-based languages bearable, my basic argument still holds. Note that I wrote this article in 2011 when (to my knowledge), there were no good automatic formatting engines for C/C++, but of course now there is ClangFormat and I use it all the time.

      But I don’t see how this places Python at a *disadvantage* compared to a C programmer with ClangFormat. Surely any good text editor has a block indent/outdent feature. So moving Python blocks into or out of a loop is very simple: select all the lines you wish to indent, hit Shift+> (in Vim, for example), and you’re done. It’s still simpler than manually inserting braces and then running ClangFormat.

      My original point, which I still stand by, is that in Python you shouldn’t think of intentation as “extra time spent prettying up the code”. Manually setting the indentation in Python *is exactly equivalent* to manually setting braces in other languages, except with the added bonus (admittedly less so now that we have ClangFormat) that your code is automatically readable.

      There’s still the problem of any C code that *hasn’t* been run through ClangFormat, such as old code, and code your colleagues may write. The advantage of Python is that correct indentation is fundamental to the language, not an optional tool you can run. This bug simply can’t happen in Python:

      if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
      goto fail;
      goto fail;

  11. This whitespace thing with python really makes me laugh. Except that I have to program in it. My favorite thing is when the pythonistas claim that it is okay to have the language not enforce object member privacy (such as is done in java and c++), because, and I quote, “We are all adults here” and you’re just not supposed to access private data outside the object. Okay, fair enough, except that apparently, we are “all adults here” only when it suits their fairly lame arguments, but are we “adult enough” to decide how and when to indent? Hell, no. Welcome to python, where everyone is assumed to be a novice programmer. The very first set of lines I have to mark as continued over several lines makes less readable crap than any set curly braces ever will.

    Python is the woodpecker of programming languages. Really, you may be around for a while, but guaranteed using your head as a hammer will not set you up on the path to higher evolution… And rarely has a language developed such an amazing number of fanboys. A fanboy is one who cannot be convinced, no matter the evidence or argument, that they may be overstating things…just…a…little…bit. “why-pythons-whitespace-rule-is-right” is a perfect example of such. [face palm]

  12. […] without most of the keywords, parentheses and brackets. It uses whitespace to determine scope, like Python. It also supports classes. These two lines define a method of the TextEditor class called […]

  13. It is true that in general we all agree indentation is important and great, but I don’t think that’s the case we can agree always in specifics.
    If you spare me the “all-code-should-be-beautiful”, which is in an ideal world, which we are not in,
    if I want to write a statement across multiple lines, python makes this ambiguous or cumbersome with ‘\’
    In C# statements like
    thing.Where(i => i func(j));
    Read nicely. All I have to do to make sure my spacing is fine is to do Ctrl+k+f (format)
    I can’t do that in Python.
    I can’t do
    int func (a) { return func(a, default) }
    If I collaborate in code, i’ll likely have to enfore spaces vs.tabs, and number of spaces and so on,
    so I don’t Really GAIN anything.

    While it is true that braces are in general redundant, in specific cases they are useful,
    1. They make whitespace not-significant, for those annoying cases (which are the ones that matter) where we need them to be insignificant
    2. They permit auto-formatting
    3. It is totally unambiguous.
    4. I have no idea how collaborating across different teams/refactoring where the whitespace can go to hell easily is executed by python programmers, but if whitespace can be a pain non-sensitive languages, I can only imagine in python.

    It’s not the only logical choice. Just a pedantic one.
    I rather control my whitespace for maximal readability,
    The compiler doesn’t understand readability, I do.

    I seriously love most design decisions of python, but that one is just such a waste.
    Either way, we may as well argue about the existence ghosts, you’ll never change your mind.

  14. Note that I wrote this article in 2011 when (to my knowledge), there were no good automatic formatting engines for C/C++. The visual studio team will be very upset…

  15. I agree with King Beauregard, any language where indenting is significant to the syntax is idiotic. I’m surprised at how many people are coding in this language. I would never think about using such a language.

  16. Requiring indentation is a great feature of Python. However it comes with a potential for annoying indentation errors that can be very difficult to spot. Take a look at this code in the image in the link below. It’s Python code written in Sublime Text 3. There’s an indentation error in there. Can you spot it? if not (and I don’t think you can) how will you easily correct it?

  17. Yes there’s a space in there between the tabs, but it’s not visible: the indentation is visually exactly the same. I don’t know why this is, because with an extra space in between the tabs I would expect a slight indentation to be noticed visually. But it isn’t. Anyway the editor can be made to show tabs and spaces by selecting all code and thus the culprit can be found, which does makes it a whole lot easier.

    This is shown in this screenshot, its the dot in line 6. Perhaps this is how people usually finds indentation errors but I just found this out now lol 😉

    • Ah, right! Yeah, as I said, I think the problem here is mixing tabs and spaces (not the whole whitespace-as-syntax concept). And I think Python would be better if it didn’t allow you to mix.

  18. Just the fact that you rely upon *non-visible* (i.e. not printable) characters tell me whomever made this decision is a moron.

    • Space is absolutely visible and printable… in fact, it drastically affects the way humans read code, so it’s clearly visible. The fact that it’s so vital for reading code is why it makes so much sense for the compiler to use the same indicator for its own parsing.

  19. Except that there are a multitude of non-printable characters – which produce “whitespace”

    Here are the most common:

    SPACE (codepoint 32, U+0020)
    TAB (codepoint 9, U+0009)
    LINE FEED (codepoint 10, U+000A)
    LINE TABULATION (codepoint 11, U+000B)
    FORM FEED (codepoint 12, U+000C)
    CARRIAGE RETURN (codepoint 13, U+000D)

    Which of these would you like inserted in your source code ?

    • Ideally, just SPACE. But obviously there are people who prefer TAB for indentation, and they should be accommodated. No code ever needs to use LINE TABULATION or FORM FEED or any other control character (other than TAB, CR and LF), so those can just be syntax errors.

      Newlines are, obviously, recognisably different to SPACE/TAB so they form a separate part of the language syntax. There’s no confusion there. There *is* confusion between CR, LF and CR+LF, but that’s fine, we can just permit all of them and treat them the same.

      The only *real* issue with having SPACE and TAB allowed is that TAB indents different amounts on different systems, so mixing them is a problem. This has been discussed at length in the comments above; in summary it’s a general problem in any language (you SHOULDN’T be mixing them). My ideal language syntax would make it a syntax error to mix SPACE and TAB in the same block; then the source code is unambiguous.

      PS. The argument that multiple characters can be indistinguishable is more general than whitespace characters and isn’t generally accepted as a reason to not have those characters be meaningful in programming language syntax. For example, many languages allow non-ASCII letters in their identifiers which means you can have ‘a’ (U+0061 LATIN SMALL LETTER A) and ‘а’ (U+0430 CYRILLIC SMALL LETTER A) as distinct identifiers. That isn’t something that generally needs to be enforced at the language level, because programmers are generally going to avoid using both.

  20. And yet I notice you use punctuation at the end of your sentences. Why not just end in white space? Because it flat out is just not as readable without punctuation. It’s hard to figure out why you even bother trying to make this argument. (And, admittedly, why I continue to follow it, ha!)

    • > It’s hard to figure out why you even bother trying to make this argument.

      The fact that one of the most popular programming languages of all time uses whitespace means it’s at least worth talking about. That’s not to say it’s valid, but I’m a bit baffled by all the people who dismiss it as so obviously wrong it’s “not even worth arguing about”.

      The analogy of punctuation is flawed because I put spaces between all my words; if we ended sentences with spaces too there would be no way to tell the difference between word and sentence boundaries.

      Also prose text is totally different to programming code. Precisely the argument I made in this article is that programming code is already indented by all serious programmers (unlike prose text, which lacks much physical structure other than paragraphs), and therefore, punctuation isn’t necessary because the indentation is so readable and noticeable.

      • Well, you certainly made a jump from ‘not even worth arguing to making’, to claiming that every language that does curly braces is wrong.

  21. PHP is popular as well. Does that make it readable? No. I will give you that a fair number of people have drunk the cool-aid, yes.

    But to the point. There is only _more_ readable and _less_ readable code. And python makes many egregious readability choices. Invisible block termination is just but one.

    If I have 3 blocks deep that drop back to 0 blocks deep, this is far more readable:

    lots of code, how deep is this at this point? (i’m a maintainer, not the author)

    more code

    and this is quite a bit less readable

    lots of code, how deep is this at this point?

    more code

    hmmm… better scroll back up and try to count indentations up the page somewhere… :-p


    and then there is the immensely ugly I’m-not-done-yet! notation. kinda, heh, “bash” to the future, i guess.)

    from nexus.cmd.resp.cli.network_config import NetworkConfig \
    as NetworkConfigCliResponse

    and the not ugly this-is-when-i’m-done notation:

    from nexus.cmd.resp.cli.network_config import NetworkConfig
    as NetworkConfigCliResponse;



    seriously? freaking seriously?? what, did they run out of underscores in the beginning programmers lab downstairs? or at least train some damned camels! concatenation of words into one long hot mess is the opposite of readability. again. how is this even debatable?

    • these code samples should look something like so:

      …………lots of code, how deep is this at this point? (i’m a maintainer, not the author)

      more code


      …………lots of code, how deep?

      more code


      from hank.cmd.resp.cli.network_config import NetworkConfig \
      ………………………………………………………………… NetworkConfigCliResponse


      from hank.cmd.resp.cli.network_config import NetworkConfig
      ………………………………………………………………… NetworkConfigCliResponse;

      • I consider it more important (when reading code) to know *what scope I’m in* (i.e., what column it starts at) than how many scopes ended at a particular point. I’m not even sure what question can be answered by counting the number of close braces. It’s much more important to know which lines of code share a start column (i.e, share a scope).

        In *all* languages, you read this by looking at the column alignment. But only Python makes sure the compiler agrees with your indentation.

        The backslash thing is a bit ugly I agree.

        > isinstance(…)

        Now you’re getting way off topic. I’m not defending all of Python. Just its indentation syntax.

  22. sigh. the formatter at this site appears to agree that whitespace is a trivial thing that should just be ignored outright. :-p

    • Yeah I know, I know. I addressed this … whoa four years ago:

      “It’s true, but I consider this to be a deficiency of WordPress, not Python. While it would be less common to do so, I could write a blogging tool that strips out curly braces, and then C code would break. I consider “readability” and “looking like it does what it actually does” to be more important design goals for a programming language than “will the code break if pasted into random website X?””

      • I was being facetious about the site editing out whitespace. Nothing to do with the issue at hand, and I’ll agree some was off-topic, but the bigger issue is readability. And to me the whitespace issue is part and parcel with a range of decisions. But I’m annoyed that you didn’t get drawn into the gratuitous provocation nonetheless. 🙂

        That said, I disagree that knowing how block scope is changing is not as important. As a senior engineer on my team, I spend an unfortunate amount of time reviewing code, and I quite often find myself backing up looking for clues to what the indentation level is. You are right that braces don’t entirely cure that issue, but they do give you twice as many cues as you get in python.

        • And more importantly, those cues are at the right place- every place such a change in scope is occurring.

  23. Reading back a bit, this is the most insightful comment made in this thread (and it wasn’t by me. go figure…)

    ZhadowOfLight said:

    “The compiler doesn’t understand readability, I do.”


    • That statement sounds like (in general) an argument against machine-automated formatting, with an attitude of “humans should format code in the most aesthetically pleasing way; it isn’t something we can leave up to an algorithm”.

      The more programming I do (on larger scale projects), the more I disagree with this attitude. When you work on a large project with code reviews, it’s amazing how much time you save by replacing two humans constantly arguing about minor formatting details with a script that just makes a decision. Not necessarily the most “pretty”, but applying a consistent rule that we can all understand. Python doesn’t really require an auto formatter, because the most significant formatting rules are enshrined in the language.

      “readability” is enhanced by consistency. I can open up a C/C++ codebase and find end-of-line opening braces, on-a-line-by-itself opening braces, a mandatory-braces-for-all-blocks rule, no-brace-on-a-one-line-block rule, optional-brace-on-a-one-line-block rule, etc, etc. I have to adjust to each author’s personal style. All Python code looks more or less the same. Compilers don’t have to understand readability, they just have to enforce a consistent rule and readability will happen.

      • But you can enforce such rules with all manner of auto formatters and with clear policies. There is no “argument” about the right way to do it. The lead engineer talks to others in the team and then makes the decisions. As such a lead on a very extensive library, I am open to debating, but after I make a decision, continued arguments about it are invitations to go work on something else.

        For the language itself to force a poor (imo) decision in regards to this matter is just a bad.

        The problem here is that you feel that python syntax forces more readable code, and I think it forces less readable code. And this is the entire crux of the debate here. Yes, consistency is very important. But consistently poor isn’t really what we’re after here.

        I’ll stand by ZhadowOfLight’s statement on this one. Likely we are at a stalemate here…

  24. “There is not a single situation in any country, in any programming language, or at any skill level, in which is it acceptable to not indent your code the way Python requires it”

    “if(condition) response();” is perfectly well accepted code. Your assertion is false afaict

    Additionally, purporting your opinion to be the correct one doesn’t help my opinion of you

    • “There is not a single situation in any country, in any programming language, or at any skill level, in which is it acceptable to not indent your code the way Python requires it”

      “if(condition) response();” is perfectly well accepted code. Your assertion is false afaict

      That style is also allowed in a single line in Python:

      if condition: response()

      Further, you may be able to find other edge cases that some style guides consider to be acceptable (like “if (condition) response(); else otherwise()”) but those are generally frowned upon, and better to split across lines once it’s that complex. Python accommodates for pretty much all indentation styles that people use.

      Additionally, purporting your opinion to be the correct one doesn’t help my opinion of you

      How do you suggest I express my opinion? I’m not simply claiming it’s correct, I’ve made a logical argument which you can either accept or dispute. Don’t tell me I’m not allowed to present a reasoned argument to support my own opinions on my own blog.

      • When I am triaging a bug, I often might want to place diagnostic code inline. There is your “single instance” when obviating standard indentation rules is completely fine and acceptable. No, I do not want my diagnostic code to “blend in” in the manner that python forces me to do. I want it front and center and obvious that it needs to be removed when I am done. That again is clear to the human reader of that code. Why does python need to “get it”? It is not python’s job to get that. Yet it still demands its opinions on the matter be inserted into the issue. Ugg!

  25. The article’s premise is fundamentally flawed. It is based on the argument that (quote) “There is disagreement over tabs vs spaces, the number of spaces, etc, but we all agree that indentation is good”.

    No one said code needs to be created by humans let alone readable by humans, because code generators. And code compressors/obfuscators are useful or they wouldn’t exist.

    It is languages like Python and make that mean we all have to cruft up our editors with “enable whitespace visible” flags. Sigh.

    • I addressed this above:

      Look, there are exceptions to this, but in general, computer code IS written by humans for humans. Machines don’t give a shit about variable names, data types, structured blocks, lexical scoping, etc. Those all make life easier for programmers. The entire point of a programming language (as opposed to machine code) is to make life easier for humans at the expense of the computer.

      If you are generating code, that’s fine, but you are going to have to work against some of the features that were designed to help humans, and that is NOT a good reason to redesign a language (unless you are SPECIFICALLY designing a language for machine generation, like LLVM).

      For a good case study on this, compare C and LLVM. I’ve hand-written code in both languages, and I’ve machine-generated code for both languages. C is horrible to machine-generate for because you have to make sure you’re coming up with unique variable names, type-casting correctly, etc. LLVM is horrible to hand-write but beautiful to machine-generate because you can just use numbers for variable names. Different tools for different purposes.

      My premise is: “Say you were designing a tool for a human, how would you design it for maximum comfort?” You’re essentially saying (by analogy) that my premise is fundamentally flawed because I haven’t thought about how dogs can operate it.

  26. You have two choices:

    Pythons way:
    + You save one character (the end brace).
    – Code breaking compatibility issues with different styles of indentation (tabs, 2 space, 4 space..)

    The normal way:
    + Compatibility issues are only cosmetic. Code will run fine.
    – You type an extra character

    Using any decent IDE you can make it auto insert indentation and closing braces, so that becomes moot, leaving only the compatibility issues (cosmetic vs code breaking). As you said, everyone indents anyways, so forcing it offers no advantges.

    And you claim pythons way is the “only logical choice”..

    • “You save one character” is not a fair summary of my post (the only positive you’ve listed for Python). I’m getting kind of sick of responding to the same comments over and over again (misrepresenting or ignoring my argument) on a blog post that is six years old. Read my replies to the above comments.

      It isn’t correct to use the word “cosmetic” (referring to a mismatch between what the code actually does and what it *looks like* it does). Cosmetic is whether you prefer 2 or 4 spaces, or whether you prefer single-line if statements to be all on one line. If there is a mismatch between what the author/reader thinks and what the compiler thinks, that can be catastrophic (see: goto fail). That is precisely my argument: whitespace-sensitive languages guarantee that the compiler and author/reader are in agreement (at least as far as block scopes go); any other scoping syntax allows for mismatch.

      Yes, IDEs can automatically do it for you, but this assumes everyone is using the right tooling. If you are reading code, you can never be sure the author used an IDE that auto-indents correctly (the author of the “goto fail” bug certainly didn’t). Whereas Python makes it structurally impossible to make this mistake.

      I’ve addressed the mixing tabs/spaces argument several times above: Python shouldn’t allow mixing tabs/spaces (that was a mistake). Either style is fine but a programmer should never mix them, and so that should not be a problem.

      • Ok so in addition to one saved character, another positive thing about Pythons indentation system is that it guarantees that a human will read indented blocks the same way as the compiler. This is a “strong guarantee” as opposed to a “weak guarantee” where an IDE does it for you.

        My conclusion is still the same:

        It causes more problems than it fixes. Your code will break if you copy in some code that is formatted differently (2 space vs 4 space) with pythons indentation system. Copy pasting python code from your browser comes to mind. Your code will not break when using a system that uses braces. In fact, using braces, it is much easier for your IDE to auto-format any code to whatever your preferred style is. The goto bug you linked is why it is recommended to use braces even for one line ifs (C/C++ shouldn’t allow braceless ifs, that was a mistake). Braces make it structurally impossible to make this mistake. If you do not follow coding conventions, you can fuck up.

        “Yes, IDEs can automatically do it for you, but this assumes everyone is using the right tooling.”

        Python already forces people to use the “right tooling” with the indentation system. Have you tried writing a quick python script in some vanilla text editor? It isn’t pretty, especially if you are a fan of spaces.

        • Hi Roger,

          I think those are reasonable arguments. Copy-pasting can be trickier (and see comments above where the irony was not lost on me, that WordPress’s comment system fucks up Python code).

          I still prefer the Python way; I think it comes down to whether you prefer a) a structural guarantee that the indentation matches the semantics, or b) a structural guarantee that the visible characters match the semantics. You can give arguments for either.

          I have used Python in simple editors like Notepad or web editors. Honestly, I don’t see the difference there: unless you are planning to not indent your C code at all then you have to do just as much space-bar-mashing in either language.

  27. Hi Matt, I just wanted to give you a big thank you for writing this article and replying so thoroughly to these comments. After a lot of hype for Python I tried to give it a go. I got really irritated with having to be forced to use white space, so I thought I’d do a quick Google to see what advocates of Python say to defend this. I found this article, and read everything here. I have a lot of similar complaints (code refactoring difficulty and guaranteed code integrity primarily) that many other people have addressed. Most boggling to me is having to work with something I can’t actually “see”, like a gas. White space has volume like a gas, but I can’t actually see what’s there unless the IDE makes the distinction of which character it is. It could be a space, a tab, a hard space, possibly a null character. I was hoping to be swayed, but you seem to misunderstand a lot of the arguments that people are making and default to curly braces being “redundant”. Since you decided to write a programming language that depends on white space formatting, I can only assume that you are completely bought-in to this. Honestly and without sarcasm, I can say am happy that I could be convinced to avoid Python by someone who is so all-about this white space. Thanks again.

  28. Very well discussed blog, with convincing arguments in both directions. I’m currently designing my own domain-specific language and had originally thought to use indentation as Python does. It was only when I tried to write a context-free grammar that I realised you can’t do that for an indentation-based language (at least not to the byte level). Python gets around the issue by introducing INDENT and DEDENT tokens, so it’s only context-free at the parsing level. I’m still undecided about whether whitespace should be syntactically significant but this well maintained blog has given me lots to think about. Thanks for taking the time to respond thoughtfully to each comment.

    • It’s a good point about it making the language not technically context-free. But I think it’s fine splitting it up into a separate tokenizer phase with a custom algorithm and a context-free (in fact, LL(1) which is super easy to parse) grammar. At the end of the day, it’s all about making life easier for your humans.

      (And yes, it does make it harder to machine-generate code, but I would argue — and have in the comments above — that that should never be a concern when designing a human-writable programming language.)

  29. I agree that a programming language should be designed for humans, not computers. After all, a computer only works with machine code, essentially strings of 0’s and 1’s. And if the language can also simplify parser development [as you say, ideally LL(1)], it’s more likely to be adopted. JSON is a good example, although that’s only for data.

    Judging by the reactions to this blog, a lot of programmers have tried both braces and indentation, yet still strongly favour braces. I can resonate with some of their concerns. Braces can be a better visual indication of scope, although I think that only applies to Allman-style vertical alignment. I still struggle to follow K&R-style JavaScript. The downside is the extra vertical space and, as you have gone into at length, properly indented code (which everyone does anyway) often makes them superfluous.

    Without getting too Perl-esque, it would be nice if a language allowed both forms of scope representation. Maybe more programmers would be tempted to the dark side of omitting braces (quicker, more seductive) if they were free to choose. However, I can imagine huge problems with trying to support the mixing of both forms. Like with tabs and spaces, perhaps mixing should simply be forbidden. It’s Ghostbuster Wisdom: “Don’t cross the streams.”

  30. Cool. Thanks, I will.

  31. Python’s white space is not right; any white-space-sensitive language is an idiotic design choice, as it is loaded with more problems than solutions (already outlined in some strong arguments above). Hence, the FOR arguments are weaker than the AGAINST arguments. Sorry.

  32. […] many other languages, Python considers whitespace in its interpretation, and the Python style guide recommends using four spaces for each level of indentation. It would be […]

  33. Great post. As for “mixing tabs and spaces and whatever invisible characters there are in the universe” well i’m not buying a BS like this – i’ve *never* had an issue like this throughout my whole python programmer career (like 7-8 years), so i believe this argument is made-up and has nothing to do with the real world.

  34. White space is terrible way to delineate because you have no explicit control over it. For example, on a small screen, you don’t want lines to wrap by themselves. You want to break up long lines under your control and use newlines, white space, indenting, etc., to make it readable without changing the syntactic meaning. When you cut and paste, if there are special deliminators, then you know you did not miss a line from the beginning or end of the block you are copying.

    • What do you mean you have “no explicit control”? I have a space bar and a tab key, as well as indentation commands in my editor. Those literally give me explicit control over my indentation.

    • Kirk, you may as well give up on it. White space is the least of your problems in the land of pythonic, which so many experienced engineers have been forced into because python was easy to teach to novice programmers. And it is a well known axiom both in and outside of programming that those who have little experience are always the goto folks for the best ideas. (See President, U.S.)

      I am using python now purely because it is the language that most inexperienced engineers know.

      Basically if I see one more ‘==’ sign in a requirements.txt file, I’m going to scream. Ahh for the days of CPAN when real gurus wrote modules, and they understood what the hell a Public API is supposed to mean.

  35. I highly disagree. In a modern programming language, you do not both indent the code and use braces. You just use braces and let the editor indent for you.
    In Python, that doesn’t work, and it slows down development a lot to always have to manually adjust indentation; especially when you copy-paste or cut-paste code (refactoring is so annoying in Python compared to C/C++, Java or C#).

    Also, the Python way is not new. Significant whitespace is just bringing back the old, obsolete, practice used by COBOL and Fortran (because they arose in a time of perforated cards): mandatory columns. Complete with a continuation character that further makes modifying code frustrating…

  36. Significant whitespace was also used in Miranda, Idris, Elm, Agda, Haskell, F#, ISWIM, and Yaml not exactly old tech. I think it makes code more readable because there are fewer tokens, and it looks a lot more compact. You spend more time reading code than writing it. Most editors can show the difference between TABS and SPACES, for example, in Sublime do ALT-SHIFT-P show spaces, and with one of its commands you can turn SPACES to TABS which is also easily found in other IDEs. To paste Python code here though you have to replace the TABS with …. or —- though. Copy/Pasting Python code may require you to turn spaces to tabs or Shift-TAB, but I think its worth it. Python doesn’t stop you from putting several statements in one line, splitting expressions, and using iterators or with statements you could indent or combine loops…

  37. […] has been an enormous amount of writing, shouting, and ranting about Python’s whitespace rules already, so let’s just jump past […]

  38. I can’t believe a few folks actually complain about having to type a delimiting character like a curly brace – as if that were some monumental effort – especially nowadays when the IDEs themselves – the real things that should be human-friendly – do all that for you (and OMG, what a saving! Puh-lease:)). The other huge problem with whitespace delimiting is that now u have to pay more attention to indentation rules and subordination. Also the fact that not every dev uses tabs/tab widths/spaces the same way in their editors. This is where formats like YAML fall down also. Often times, you’ll get unexpected (in/out)dentations that throw off/create new the subordinations unintentionally. The problem is now u have to pay more attention to stupid stuff like that, so it’s actually adding more ancillary worry/attention, extra editor standards, etc. to police when we should be at a point where we’re reducing that stuff. Worse, automated build pipelines don’t afford the chance to glean these indentation discrepancies beforehand like humans/IDEs will before producing errors. The code is definitely not more readable just because u get rid of a few tokens per line; are humans REALLY having that hard of a time reading traditionally delimited code? Gimmie a break. Why now? I haven’t heard 1 complaint about that in my 35 years in IT. What I do see is the industry creating problems where they never existed, just to push new crap on us. The price of progress I guess, esp during the periods of stagnation. Delimiting chars give more visual structure to code; gotta remember, code isn’t something u read like regular prose/sentences; ur eye can discern content much better in a columnar fashion that horizontally anyway, and that’s the more appropriate model for code syntax digestion. Keep in mind that this was all hashed out a long time ago folks; there are reasons why they didn’t go w/ whitespace delimitation in the 1st place – even back when coding required more typing/the IDEs were less friendly/did less for u!

    This is like the ridiculous argument that JSON was more human readable than XML; bullshit. And then to add insult to injury, someone actually thought to create YAML as more human-readable than JSON! Folks, you’re putting in all this work for the 1 entity that’s the best at “OCR”ing letters/deciphering groupings – humans – who ironically don’t need all this help!! Please, put that energy into solving actual problems.

    • That would be at least two delimiter characters, because of the ending semi-colon on nearly every damn line. And Vim doesn’t auto add that stuff for you so you have to type it yourself every damn time, and I’ve not seen an IDE which will auto open curly braces for you, though they do normally auto close them for you, or add semi colons onto the ends of your lines.
      That curly brace key is not in the friendliest place for typing in the world either.

      Also, YAML is great I love it and it is much more readable than JSON. JSON coming from the JS world has the much less readable 2 space indenting rule often times and that’s just too little indentation to work out the structures.

      Anyway, it seems that near everyone thinks that indentation helps readability, otherwise you’d just use those delimiter characters you like so much and not bother with using the tab key at all, why waste your time pressing those additional buttons if they don’t help anyone because all you need is to read the delimiter characters? Try it, I’m sure either you, or if you have colleagues, will realise the error of your ways and will quickly return to indentation and if you have to indent to show delimitation then why do you need delimiter characters?

  39. […] has been an enormous amount of writing, shouting, and ranting about Python’s whitespace rules already, so let’s just jump past […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: