PEP 8: Hanging Indentation and Closing Brackets in Python

PEP 8 purists are ready to attack you and your code if they catch you not complying with the PEP 8 standard. For instance, Python coders put their braces, brackets, or parentheses into a separate line to make it easier to grasp nested lists or dictionaries.

This article shows how to line up the closing braces, brackets, and parentheses correctly in Python. This is called “hanging indentation” and it’s at the heart of PEP 8 standardized, clean code that’s easy to read and understand!

A quick example shows how you can create a multi-line construct that complies with the PEP 8 standard:

# PEP 8 Compliant
age = {
    'Alice': 24,
    'Bob': 28,
    'Ann': 26,
    }

So, how to correctly intend list or dictionary data enclosed in braces, brackets, and parentheses?

According to the PEP 8 standard, there are two ways to line up the closing braces, brackets, or parentheses. First, line it up with the first non-whitespace character of the previous line. Second, line it up with the first character that starts the multi-line construct.

This sounds a bit confusing so let’s hop into practical examples.

Where to Put the Closing Brace, Bracket, or Parenthesis?

For multi-line constructs, there are two basic options of how to correctly intend the data.

1. Align the closing brace with the first non-whitespace character of the previous line:

# PEP 8 Compliant
age = {
    'Alice': 24,
    'Bob': 28,
    'Ann': 26,
    }

2. Align the closing brace with the first character that starts the multi-line construct:

# PEP 8 Compliant
age = {
    'Alice': 24,
    'Bob': 28,
    'Ann': 26,
}

Both ways of indentation are equally valid according to the PEP 8 standard. But note that in any case, the opening and closing braces (brackets, parentheses) should be placed in their own line. So the following would be a violation of the PEP 8 standard:

# NOT PEP 8 COMPLIANT
age = {'Alice': 24,
       'Bob': 28,
       'Ann': 26,
       }

The reason is that both opening and closing braces (brackets, parentheses) should be placed in their own line.

However, the PEP 8 standard allows NOT to place both opening and closing braces (brackets, parentheses) into their own line—IF the arguments or items align. Here are three PEP 8 compliant examples:

# PEP 8 Compliant
def f(argument_1, argument_2,
      argument_3, argument_4):
    None


# PEP 8 Compliant
def f(argument_1,
      argument_2,
      argument_3,
      argument_4):
    None


# PEP 8 Compliant
def f(argument_1, argument_2, argument_3, argument_4):
    None

Although the opening and closing parentheses are not placed into their own lines, it’s still PEP 8 compliant because the arguments align in the first two examples.

The following interactive code is not ready, yet. It requires your debugging superpower:

Exercise: Debug the code so that it runs. Which indentation method is your preferred one?

Why End Python List with Trailing Comma?

We’ve seen many examples of multi-line constructs where there’s a trailing comma after the last list element:

# PEP 8 Compliant
age = {
    'Alice': 24,
    'Bob': 28,
    'Ann': 26,
    }

The trailing comma after the last line in the dictionary ('Ann' : 26,) is optional according to the PEP 8 standard.

Be aware: you’ll find many opinions on the web where “experts” tell you that the trailing comma is required (like here). But this is not explicitly stated in the standard. In fact, the standard recommends that you use the comma if your “items [are] expected to be extended over time” (source). In this case, it’s easier to copy&paste new items into the list (or dictionary) without having to manually add a trailing comma to the old last item and removing the trailing comma after the new last item.

In other words, the following multi-line construct is also valid and implicitly follows the PEP 8 standard:

# PEP 8 Compliant
age = {
    'Alice': 24,
    'Bob': 28,
    'Ann': 26
    }

Note that the trailing comma is missing. But if you don’t plan to extend your list over time, it’s fine to use this—even if some Python code style checkers (“Linters”) complain.

Nested Multi-Line Constructs

Now, you simply need to decide about which of the above methods you prepare to write opening and closing braces, brackets, or parentheses. Here’s how you can nest those and comply with the PEP 8 standard:

# PEP 8 Compliant
data = [
    'string',
    42,
    {
        1: '1',
        2: '2',
        42: '21',
    },
    (1, 2, 3),
    (
        [1, 2, 3],
        [4, 5, 6],
    )
]

You see that we place each brace, bracket, and parenthesis in one line. The next line starts with four whitespace indentations. Then comes the item, followed by a comma. The item itself can be a multi-line construct as well. But if you understand how to write one multi-line construct, you’ll also understand how to nest them.

Similar Questions

Should curly braces appear on their own line?

Yes, they should appear on their own line. An exception is if you write the whole sequence of items in one line. In this case, the closing brace, bracket, or parenthesis should appear at the end of the same line, too.

Where to Put the Closing Brace?

As discussed previously, you line it up with the first non-whitespace character of the previous line, or with the first character that starts the multi-line construct.

Flake-8 Rule: Continuation line unaligned for hanging indent (E131)

This is a common error of the code analyzer Flake-8. A continuation line is unaligned for hanging indent.

Anti-pattern:

# NOT PEP 8 Compliant
my_dict = {
    "key": "value",
    "long": "the quick brown fox jumps over the "
        "lazy dog",
}

Best practice:

# PEP 8 Compliant
my_dict = {
    "key": "value",
    "long": "the quick brown fox jumps over the "
            "lazy dog",
}

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!