Skip to content

Python indendation rocks (and sucks a little bit).

May 30, 2008

Andy Buckley wrote a blog about why Python indentation was bad. He has two arguments, and one example. Fortunately, he is mostly wrong. He is right about his first argument: Invisible syntax isn’t really a good idea. A really good example of invisible code was old to me by a friend in Sweden many years ago. There was a programming language, I’ve forgotten the name, where any characters where allowed in variable names. For a joke, people would insert the escape codes for colours in the variable names, so you would have a green variable, named red, and a red variable named red. Highly confusing. Then somebody figured out you could call the variable <escape to red><escape to red>red<escape back>. This would of course be completely indistinguishable from the other red red variable, and make the program incomprehensible.

Yes, invisible syntax is bad, and if you mix tabs and spaces in Python, the syntax indeed becomes invisible. Andy will without a doubt be happy to know that Python 3 will no longer allow it. Try it and you get “TabError: inconsistent use of tabs and spaces in indentation”. This news was greeted at PyCon this year with loud cheers. That means that with Python 3, the syntax is no longer invisible. You will see the difference in indentation, the indentation can no longer be ambiguous. Yes, you can still mix three spaces with two spaces and one space and ten spaces. But that doesn’t matter. Inconsistent indentation might be confusing, but no more so that inconsistent variable naming, and is no fault of the language.

The second reason from Andy is that you can’t use tools to fix the indentation. But this is in fact incorrect. If the indentation is broken, that is a syntactic error. It’s a bug. You can’t use tools to fix bugs, you need a programmer. His has an example of broken indentation and asks how it should be fixed. It’s this:

def myfunction(foo, bar):
    foo.boing()
   for i in bar.fizzle(foo):
      baz = i**2
    foo.wibble(baz)
    return foo, baz

Well, but with braces, that code would look like this (or similar, the indentation errors makes the code ambiguous, so there is alternative ways of misplacing the braces.):

def myfunction(foo, bar): {
    foo.boing()}
   {
   for i in bar.fizzle(foo): { {
      baz = i**2 }
    foo.wibble(baz)
    return foo, baz }
}

How would you correct that? Which braces are incorrect? There is an error in how the blocks are created, and you can’t fix that with a tool, no matter if the blocks are created with brackets or white space.

Andy’s real world example is that he needed to cooperate with somebody whose editor liked using a mix of tabs and three-space indents. First, delete that editor, or fix the configuration. Secondly, as long as the indentation in fact is correct, you can fix it. The confusion comes if you use an editor where you have said that tabs should be shown as equal to four spaces, and you mix tabs and spaces. Then you can get things that look like this:

def foo():
      for x in range(5):
    print x

And you go “wha?” Because that print line starts with a tab, which is expanded by python to eight spaces, but shown by your editor as four. And the line before contains six spaces. So, Python will interpret this correctly, your editor will not. However, if you look at the file with “less” it will look OK. These type of problems are fixable. You can use a script that replaces all tabs with spaces, correctly. Then the file will look OK. And if the indentation after this is a mix of two, five and umpteen spaces, this is also fixable by tools. In fact WingIDE, which I use, will complain on mixes of tabs and spaces and ask if they should be fixed. It will adapt the indentation to what is already going on in the file, so when I get a file written with three spaces as indentation (this has happened), this works just fine, but I can also tell it that no, it should in fact always be 4 (or 2 or 6 or 9) spaces as indentation, consistently, and it will re-indent the whole file.

So, yes, invisible syntax is bad. Yes, Python 2 has it. Python 3 does not. That you can’t fix programmer bugs with tools is nothing unique for Python. You can fix ugly indentation in Python, as long as the code actually runs.

There is however one actual problem with the indentation: There is no do-until loop. And this is because you can’t write:

do:
  blablablabl
until x

This is a pity, because I want a do until loop. An alternate syntax is possible:

until x:
   blablablablabal

But this apparently has been decided against, because it means that the test comes before the code, and the variables used in the test gets defined after the test, which apparently is frowned upon from a syntactic point of view. I don’t care. I still want an until x statement, but it seems I won’t get one. And this is the indentations fault, and the only real problem with Pythons indentation as I see it. But the benefits still are so many more and so much bigger that the drawbacks get dropped-kicked into PHP-land.

From → python

26 Comments
  1. Subversion pre commit hooks should definitively discard commits of Python modules with mixed indentation (spaces+tabs)

  2. That is definitely one way to get around the problem. Also using tools like pyflakes or pylint regularly is a good idea in any case, and also I think pylint actually can reformat your code with consistent indentation, I forgot to mention that in the post.

  3. I’d like to reiterate your point about editors. They really solve the “indentation problem” Andy talks about, in all sorts of ways.

    The first thing I do when I’m in a new environment, setting up my editors is set my tab stops, and then “expand tabs” to true. This way I never have to worry about hitting tab or auto-indents adding them for me.

    Most of the time, I use Jedit, and a plugin called “WhiteSpace”. It allows you to display hidden characters (spaces, tabs, linebreaks, etc), either leading, trailing, or both. It makes obvious the sorts of tab/space mixing issues that Andy complains about, and helps with keeping indentation consistent. I’ve also recently started using the “LineGuides” plugin as well. It lets me set up visual guides every 4 columns so I can be doubly sure my indentation is correct (helpful for those times when code is in bad need of refactoring due to heavy indents!).

  4. Daniel Diaz permalink

    Bah.. I use notepad😉

    Seriously tho, programmers are anal retentive by nature. I think this is particularly true with Pythonistas. These are ppl who not only want to code but want to code elegantly (i.e. nice spacing, consistent blocks, etc), so this indentation is not so much of a problem for them (including me!).

  5. I think Andy might have been a little too enthusiastic. While the whole indentation thing can certainly be annoying, it’s not really dangerous. The proof’s in the pudding. There’s a lot of sweet Python running just fine and making people money.

    If indentation was a true deal breaker, the language would have either petered out or the changes would have been made long ago.

  6. It’s true that Python wouldn’t have become as popular as it s if indentation was a bad idea. Languages that depend that heavily on bad ideas tend to stay esoteric.🙂

    But indentation can be annoying if it’s done badly even if pylint can fix it. But as mentioned the major annoyance will go away in Python 3. Python 3 is really very very nice. See my other recent posts on this.🙂

  7. grunged permalink

    I have been coding in python for the past four months and am especially bothered by this indent thing. I have a dual boot system and often switch between windows and linux, coding in notepad++ or in gvim or in Kate. I also have access to a server machine where I use vim. Sometimes I upload some code on the server, and sometimes I edit it there as well. Due to some bad settings in one of these, some of my files now have both tabs and spaces and I do not know what to do. Frankly speaking, you cannot get away by classifying random editor settings as programmer errors – seriously, it feels like the developers of python are putting their share of the blame on me, the user.

    Thankfully, python 3.0 addresses some of these issues (but what if one of my editors has a 3-space tabbing setting, and another one has 4-space tabbing settings?) And what if you use spaces to indent one day and the other day your vimrc goes missing and you indent the 2nd part of the same block with tabs (and now of course it isn’t the same block!). You can always say “dump that editor” or “you’re stupid to make such a mistake”, or “use a better editor” but frankly, I was happy coding java using edit, and I never had any problems with that (and I was indenting properly as well, since readability had been so well stressed upon by my high-school computer science teacher). The point is, such annoying errors can and do occur in python, which are more difficult to locate than the corresponding brace errors, and it does reduce the productivity – and the fact that they are caused by a whimsical design choice, makes it even more annoying.

    Another indentation-related issue is writing code at the end of a deeply nested block :

    block1:
        block2:
            block3:
                block4:
                    block5:
                    block5:
                    block5:
                    block5:
                    block5:
                    block5:
                    block5:
        block2 more code, written in anxiety wondering to which block it actually belongs

    A similar problem is there in C or Java as well, but I’d trust braces over indent any day.

    • What to do about mixes? Search and replace. Replace the tabs with spaces. Done.
      I have a hard time believing there are programmers editors where you can’t change these settings today.
      The problem of seeing what block code belongs too is even bigger in C and Java, as you actually can have one indentation and another bracketing, and hence simply trick yourself.

  8. In a badly indented python code one would have to scratch their heads a couple of times before deciding which tabs to convert and to how many spaces. Thankfully, reindent.py solved a few of my problems. But I can’t be sure if in a big project such an accident cannot happen. I guess it’s a matter of taste, if you find such errors annoying or not. i guess all I can do is be more careful (or not program in python if I can?).

  9. Accidents? Yes, people mixing tabs and spaces happens in all big projects. Yes it’s annoying. That’s completely independent on the language.

    But with other languages you have to keep two different ways of making blacks in sync: Brackets and indentation. In python there is only one. This makes for *less* accidents.

  10. grunged permalink

    [quote]
    Accidents? Yes, people mixing tabs and spaces happens in all big projects. Yes it’s annoying. That’s completely independent on the language.
    [/quote]

    except, in some languages that does not affect the logic.

    [quote]
    But with other languages you have to keep two different ways of making blacks in sync: Brackets and indentation. In python there is only one. This makes for *less* accidents.
    [/quote]

    except, I can copy an already working code block from someone’s code and paste it into mine and be perfectly sure that it works fine.

  11. It doesn’t affect the logic in Python either. How many spaces you expand your tabs to in your editor doesn’t affect the logic of python programs.

    If the code mixes tabs and spaces in a bad way, and your editor replaces tabs with less than eight spaces, then yes, it will stop working. But it will also obviously be incorrect if you do that. Would you paste in code into your program and NOT fix the indentation even if it was another language?

    Incorrect code can look correct if you have set your tabsize to anything other than eight. So don’t do that when editing python code.

    Honestly there are thousands of Python programmers that develop in python every day and never have problems like these. I personally haven’t had any tab problems since 2000. Just make sure your editor shows tabs as being 8 spaces wide (which is what Python thing they should be) and all will be fine. Honestly.

    http://www.secnetix.de/~olli/Python/block_indentation.hawk

    Python indentation is NOT a problem. You may not like it, it’s a matter of taste, but it is NOT a problem.

  12. is there an option to tell the interpreter that I’d be using only tabs or only spaces or equal-sized block indentations at the beginning of the code, and please invalidate any other type of indentation[or, is this feature available in any editor]? If not I think this would be a nice feature added to Python

  13. something like :

    #!/usr/bin/python
    #define INDENTATION_STYLE SPACES_ONLY
    #define INDENT_WIDTH 4

    (sorry for the C style syntax, but you get my point)

  14. Python doesn’t have that feature. As mentioned above Python 3 will not allow inconsistent mixes of tabs and spaces. I don’t see why you should add this to python. Python will see how you indented your file, you dont’ need to tell it. If you want to check your code you can do that with tools. If you want to reindent the code, you can do that with tools.

    Any programmers editor worth it’s salt can do this for you. As mentioned in the article WingIDE does, and will also point out if you are using both tabs and spaces and ask if you want to convert it. You can also reindent the code.

    As mentioned, there is one and only one problem. If you mix spaces and tabs in an inconsistent manner, and have an editor who will show tabs as other than 8 spaces, then you may end up not seeing what your code does.

    The solution: Don’t have another tab display setting than 8 spaces when editing python code.

  15. I’m not telling python how I indented the file; I’m telling how I intended to indent the file. If some part of my code has not been indented that way, it should be seen as an error that I made. I don’t see how adding this extra safety feature won’t make programmers happy. I believe that since Python has made indentation a part of its syntax, it should provide ways to deal with it safely. I’d have been willing to take the editor argument had indentation not been a part of the language syntax.

    Anyway, I’d like to propose this idea to the community. What’s the best way to do that?

  16. “If some part of my code has not been indented that way, it should be seen as an error that I made. ”

    That is telling python. You can tell yourself with a comment.

    “I don’t see how adding this extra safety feature won’t make programmers happy.”

    I don’t see how this solves any problem. Remeber, your code will only look wrong if you have other tab indentation stops than every eight characters. From the python docs: Tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight (this is intended to be the same rule as used by Unix). There is no way your code can look wrong if your editor does this too, and this is what editors do by default.

    Python 3, as mentioned, does this differently, and there you can not have the problem at all.

    “Anyway, I’d like to propose this idea to the community. What’s the best way to do that?”

    Send a mail to python-dev@python.org. But just so you know: You are going to get shot down in a hailstorm of flames. You are suggesting a non-pythonic way of solving something that is not a problem.

  17. grunged permalink

    “But just so you know: You are going to get shot down in a hailstorm of flames.”

    Don’t worry, I’ll think this through before posting. If I succeed, it’d make the life of a few of us happier, and a few unchanged. If not, that’d just add some spice to my mailbox.

  18. Well, that’s a good attitude at least. But this HAS been thought through already. Your solution does not fix any problems.

  19. John permalink

    You are seriously full of it. At least with the curly braces, you can SEE the open and close, whereas in python, the open and close is invisible. Ever tried coding fifty lines of python code with nested for, while loops and if statements?

    At least with java, c, c++ and other more standard syntax languages, there’s a visual cue where something stops and ends.

    • Yeah, I have coded way more than fifty lines with nested for while loops and if statements, even if any person in any language worth their salt as a programmer would simplify that.

      And it’s not a problem, because there is a visual cue where something stops and ends. And it’s the same one as in java, c and c++: The indentation. The brackets only get in the way, which anybody who has coded in Python for a couple of days agrees with.

      So, no, I’m not full of it: You are. Way to go to make a fool of yourself, John Safar.

  20. neeneko permalink

    Agree or disagree, people do not put words in other python programmer’s mouths.

    I have been using python almost exclusively for over a year, and I disagree that ‘brackets only get in the way’. I still prefer their explicitness to python’s invisible blocking.

    Though I am happy that the python developers did not try to do away with () on functions too. I would not be surprised if someone thought of replacing them with something involving spaces….

    • What a strange comment. Pythons blocks are not invisible, and it is explicit. It just that you can’t make indentation that disagrees with the blocks. I’ve never seen any arguments for allowing that.

  21. grunged permalink

    For people who prefer the C brackets, we can just put #{ and #} at the beginning and end of our code blocks. Everyone is happy🙂

  22. Metavoid permalink

    ahhh, that is why the program stopped working.
    I emailed it home and nothing worked anymore.

    Did not think such a popular language would be so fragile.🙂

  23. THe MOre I read the more I Miss Object Pascal.
    I was really liling Python,but this identation really sucks,I really dont mind to “lost” one line with ENDIF specially now that almost all goOd IDE have things like code Hiding and expand.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: