Skip to main content

Settling the bracket discussion once and for all

There are quite a few ways you can format a multi-line function call/list/dictionary in a programming language. With Python (at least with PEP8) it's just two ways: hanging indentation and vertical indentation. The latter is quite straight-forward and I mention it in the notes below. The former one is what this post is about. Well, about a minor but important question of where to place the closing bracket when using it.

Yes, style is much more than formatting the commas and brackets so let's settle this and move on to the more important questions.

When using hanging indentation, the only true way is this one(*):
some_tuple = (  # Nothing here, only opening bracket.
    item1,
    item2,
    item3, item4,  # Several items on one line is acceptable though not recommended.
    item5,  # Last comma is important. And never, never place the closing bracket here.
)  # Again, nothing here but the bracket and it's on the same level as the opening line.
Empty line after the opening comma is mandated by PEP8 even though there are a few cases where doing otherwise would've been a possible alternative, like:
class DoNotDoThis(object):

    def just_do_not(self,
        long_argument1,
        long_argument2,
        long_argument3=long_default_value,
    )
and there is a reason for that — anything after the bracket makes the opening line less visible. That's part of the reason for the two spaces before inline comment rule.

The last comma(†) and separate line for the closing bracket is important because you don't really want to see another commit in git blame just because another item was added or deleted and you had to add a comma or move the bracket. You you're using Vim, it also makes adding/deleting easier because you can operate with the whole lines (it helps with just any editor but with Vim it's more so).

I'll repeat: closing bracket should be on separate line and on the same indentation level with the beginning of the opening line (if some_tuple is indented by four spaces, closing bracket should be indented by four spaces).

It might sound like a minor issue but 1) it's the only meaningful way of doing brackets once you think about it, and 2) they should be formatted in uniform way throughout the code so why not pick this one from the three or four PEP8-compatible alternatives(‡). It's one of the things that are easily controllable with pep8 linter (or flake8 which I actually prefer, the same thing but better) — you might wanna configure some auto-check in your editor/IDE, most of them allow that easily (plus, autoindent helps tremendously).

(*) The only case when you place the closing bracket on the line with the last item is this (so-called vertical indentation):
call_some_function(argument1, argument2,
                   argument3, argument4)
Although I'm not fan of this style, it's been around since Kernighan and Ritchie... But still, don't do that, especially with long arguments. Also, while it's still acceptable to put a closing comma on a separate line when using vertical indentation, it looks kinda ugly for me.

(†) There is one case where there should be no last comma. If it's a function call/def and you're using *args or **kwargs. It's almost not worth mentioning because you don't add stuff after **kwargs and it would just result in syntax error if you placed a comma there (not sure why it was implemented that way, but that's the way things are). But still a separate line for the bracket is preferred.

(‡) The text of PEP8 is little ambiguous on this point and some variations acceptable by the letter of it are not allowed by the recent versions of the linter, but it's essentially three options for hanging indentation: a) closing bracket on the separate line on the same level of indentation as the items (doesn't work well with if/while/def blocks), b) closing bracket on the same line as the last item (makes editing harder and messes with git blame when you add/remove items), c) what I have presented above. (There is also d) bracket on any other other level of indentation, like four spaces more than for the items, but that just makes zero sense.)

Popular posts from this blog

Using virtualenv for more than Python projects

Sorry, it's not a complete instruction, just a thought. It occurred to me (some time ago) that Python's virtualenv is, essentially, a simplified version of system "prefix", it has bin, lib, include, and can have more stuff when needed. If you're willing to experiment (you'll probably have to set a few additional environment variables and/or build flags but that's no big deal), you can install various other tools there up until you have a complete system with its own compiler and complete set of libraries although it's much simpler to keep using system compiler and libraries only complimenting them when needed. Granted, prefixes are nothing new, people were using /opt (and their home directory) this way since the beginning of time. But with little help of virtualenv-wrapper or pyenv you can easily switch between them and isolate environments better. Binaries and stuff installed in virtualenv would override system defaults but only when venv is activat

Huawei TalkBand B3 (active) review

Despite the fact that no manufacturer ever sent me any free gadget for review, I'm continuing doing it. Maybe I'll become a popular reviewer and they will change their mind. This post will be the first in this year's wearable gadget reviews. To put it into perspective for those who don't know me, I'm not a fitness person, like at all. I eat healthy, I walk kinda a lot, I do some aerobics and occasional cardio but that's it. I'm too lazy even for jogging. But, for some reason, I currently have not one, not too, but three fitness trackers on my wrists. Yeah, crazy, I know, but that was the only way to compare them properly. By the way, wearing TalkBand on the same wrist with anything else is super inconvenient, you can hardly take it out for calls. But more on that later. Why do I need any fitness tracker? Apart from knowing time, I like to know how active I'm during the day, and, more importantly, track my sleep. I have some issues in that department so

ORICO — small things that stand out

More than once I've written about stuff made by Big Brand manufacturers so I decided to balance things out by writing about a mostly-unknown but good things. In short, if you need something small like HDD enclosure or some cable or USB hub or a dongle of some kind, check if ORICO makes it and chances are you won't be disappointed. It's usually slightly more expensive than low-end stuff from aliexpress but, in my opinion, it's usually worth it. Disclaimer. This post is a shameless promotion of their brand although, unfortunately, nobody paid me for it or even sent me any free stuff. Guys from ORICO and not, if you read this, I'll gladly review whatever free goodies you send me :) I only do honest reviews so better make sure to send the good stuff. At this point I own a USB hub, three different 2.5" HDD enclosures, and a precision screwdriver set from them. And probably something else I don't remember. Here are the pics: USB hub in its natural habitat