DEV Community

Cover image for Python PEP 8 tutorial: Get started writing readable code
Erin Schaffer for Educative

Posted on • Originally published at educative.io

Python PEP 8 tutorial: Get started writing readable code

Python Enhancement Proposal 8, or PEP 8, is a style guide for Python code. In 2001, Guido van Rossum, Barry Warsaw, and Nick Coghlan created PEP 8 to help Python programmers write consistent and readable code. The style guide may not always apply to your work, but it’s an important and useful tool that will elevate your code-writing process. Today, we'll provide a brief overview of some of the fundamental pieces of the PEP 8 Python style guide, including naming conventions, code layout, comments, and more.

Let’s get started!

We'll cover:

Why use PEP 8?

As Guido van Rossum said, “code is read much more often than it is written.” Coding involves a lot of teamwork and collaboration, which means that many different people might end up reading our code. With that idea in mind, it makes sense to spend some extra time writing our code to make sure it’s readable and consistent. We can use programming style guides to ensure that we’re creating the best code possible. When working with a new or unfamiliar programming language, there are so many rules and practices to learn. It can be hard to remember all of the conventions of the language.

Python PEP 8 helps solve that problem. The style guide was designed to help us improve the readability of Python code. It outlines rules for things like variable names, whitespace, inline comments, indentation, and much more. It’s a solid and comprehensive resource that we can use to write great code. Writing clear, consistent, and readable code is important for dev jobs. It shows potential employers that know how to structure code well.

PEP 8 naming conventions

Naming conventions in programming are very important. They improve readability and speed up development time. Remember that code is read a lot more than it’s written, so using naming conventions will help ourselves and others understand our code better. When following naming conventions, we don’t have to spend time debating what to name variables, methods, classes, or functions. We can following the naming conventions to speed up that process and code more efficiently.

Choosing appropriate names when we’re writing code will save us time and effort in the long run. Let’s take a look at some of the PEP 8 guidelines for naming.

Naming styles

Here are some of the naming conventions in Python:

  • Class names: Use camelcase. Begin each word with a capital letter. Don’t use underscores to separate words.
    • Examples: OurClass, class
  • Constant names: Use an uppercase single letter, word, or words. Use underscores to separate words.
    • Examples: OUR_CONSTANT, CONSTANT
  • Function names: Use a lowercase word or words. Use underscores to separate words.
    • Examples: our_function, function
  • Method names: Use a lowercase word or words. Use underscores to separate words.
    • Examples: our_method, method
  • Module names: Use a short, lowercase word or words. Use underscores to separate words.
    • Examples: our_module.py, module.py
  • Package names: Use a short, lowercase word or words. Don’t use underscores to separate words.
    • Examples: ourpackage, package
  • Variable names: Use a lowercase single letter, word, or words. Use underscores to separate words.
    • Examples: our_variable, x

Choosing names

It’s not always easy to choose names for your variables, functions, methods, etc. It’s important to be mindful of the names you’re choosing to make sure they’re clear, appropriate, and effective. We suggest using descriptive names to make it very clear what the object stands for. Choosing descriptive names will help you in the short term and the long term. If you use a vague name for one of your functions, you may come back to your code in a few days or weeks and forget what it means.
This is where PEP 8 comes in handy!

PEP 8 code layout

Whitespace

Vertical whitespace improves the readability of our code. Let’s look at some of the main PEP 8 guidelines on how to use vertical whitespace or blank lines:

  • Surround top-level functions and classes with two blank lines
  • Surround method definitions inside of classes with one blank line
  • Use blank lines inside functions to show clear steps (but use them sparingly)

We should avoid using whitespace in the following situations:

  • Inside of parentheses, brackets, or braces
# Do this:

fruit(banana[1], {strawberry: 2})

# Not this:

fruit( banana[ 1 ], { strawberry: 2 })
Enter fullscreen mode Exit fullscreen mode
  • Between trailing commas and a follow close parenthesis
# Do this:

foo = (1,)

# Not this:

foo = (1, )
Enter fullscreen mode Exit fullscreen mode
  • Right before a comma, semicolon, or colon
# Do this:

if x == 5: print x, y; x, y = y, x

# Not this:

if x == 5: print x , y ; x , y = y , x
Enter fullscreen mode Exit fullscreen mode
  • Right before an open parenthesis that starts the argument list of a function call
# Do this:

dog(1)

# Not this:

dog (1)
Enter fullscreen mode Exit fullscreen mode
  • Right before an open parenthesis that starts indexing or slicing
# Do this:

dct["key"] = lst[index]

# Not this:

dct ["key"] = lst [index]
Enter fullscreen mode Exit fullscreen mode
  • More than one space around an operator to align it with another
# Do this:

x = 5
y = 10
our_variable = 20

# Not this:

x          = 5
y          = 10
our_variable = 20
Enter fullscreen mode Exit fullscreen mode
  • Avoid trailing whitespace

Line length and line breaks

PEP 8 suggests that all lines should be limited to 79 characters. For longer blocks of text like docstrings or comments, the length should be limited to 72 characters. Limiting the line length helps make our code more readable. We’re able to have different files open side by side, and we avoid line wrapping.

There are some situations where teams may want to have a longer line length. The suggested way to wrap long lines is to use Python’s implied line continuation inside parentheses, brackets, or braces instead of using a backslash.

If we need to use a line break around binary operators like + and *, we should place it before the operator like this:

# Do this:

total = (first_variable
         + second_variable
         - third_variable)

# Not this:

total = (first_variable +
         second_variable -
         third_variable)
Enter fullscreen mode Exit fullscreen mode

Indentation

Indentation is very important when writing Python code. Indentation levels determine how statements are grouped together. The main PEP 8 indentation guidelines include:

  • Use four spaces to indicate indentation
  • Use spaces instead of tabs

Let's look at an example:

x = 20
if x > 50:
  print("x is greater than 50")
Enter fullscreen mode Exit fullscreen mode

In the above example, our indented print statement tells Python that it should only execute the statement if the if statement returns True.

Tabs and spaces

Spaces are the preferred way to indent code. We should only use tabs if we’re working with a piece or section of code that’s already indented using tabs. Python 3 doesn’t allow us to use both tabs and spaces to indent, which means our code won’t run if we use a mix of tabs and spaces. PEP 8 recommends that we use four spaces to indicate an indent.

Python 2 doesn’t have the same rule, which means we won’t notice errors if we use a mix of tabs and spaces. To make sure we’re using a consistent indentation method in Python 2, we can add a -t flag when running our code from the command line. The interpreter will give us a warning if it finds any inconsistencies. If we use the -tt flag, the interpreter will give us errors, which means our code won’t run.

PEP 8 comments

Comments are a big part of the coding process. It’s important to make sure they are clear, up-to-date, and helpful. Not only do comments help us, but they help anyone else that comes into contact with our code. When someone reads our code, our comments should clearly align with a portion of the code. They should also help the reader understand what’s going on in the code.

It’s a good practice to write comments as complete sentences, with the first letter of the first word capitalized. This is called a sentence-style case. If our code begins with an identifier, it’s okay to use a lowercase letter here. We should never change the name of an identifier in any way.

Another good commenting practice includes limiting the line length of our comments and docstrings to 72 characters. If our comments exceed 72 characters, we should start a new line. We should also make sure to update our comments if our code changes for any reason. Let’s take a look at some of the different types of comments and how they fit into PEP 8:

Block comments

We can use block comments to document a smaller section of code. We typically see them within functions or chunks of code or data. PEP 8 outlines the following rules for block comments:

  • Begin each line with a # followed by a single space
  • Indent block comments to the same level as the code they apply to
  • Separate paragraphs with a line containing a single #

Let's look at an example:

for i in range(0,10):
    # Loop over i ten times and print the value of i
    # followed by a string of your name
    print(i, "Erin")
Enter fullscreen mode Exit fullscreen mode

Inline comments

We can use inline comments to document a single statement in a piece of code. We typically use them to remind us why certain lines of code are relevant or important. PEP 8 outlines the following rules for inline comments:

  • Use them sparingly
  • Write them on the same line as the statement they apply to
  • Use two or more spaces to separate them from the code statement
  • Begin each inline comment with a # followed by a single space
  • Don’t use them to explain anything obvious
x = 1 # This is an example of an inline comment!
Enter fullscreen mode Exit fullscreen mode

Docstrings

Docstrings are string literals that occur as the first line of a class, function, method, or module. We can use them to document specific blocks of code and describe what the class, function, method, or module does. The main rules that apply to docstrings include:

  • Surround docstrings with three double quotes """ on either side, like this: """Hi, I’m a docstring!"""
  • Write docstrings for all public classes, functions, methods, and modules
  • When writing a multiline docstring, put the double quotes that end that docstring on a separate line
  • When writing a single line docstring, keep the double quotes on the same line

Linters and autoformatters

We can use linters and autoformatters to help us make sure our code is PEP 8 compliant. Let’s talk about them!

Linters

Linters analyze our programs and flag any errors that we have. They give us suggestions on how to fix our errors. We can install linters as extensions to our text editors, which means that they’ll flag errors as we write code. There are many different Python linters available. Let’s take a look at two of the most popular linters:

Flake8

Flake8 is a tool that combines pyflakes, pycodestyle, and a debugger. We can invoke Flake8 on the command line or via Python. We can use Flake8 to check our entire source code, or we can narrow what it checks by indicating specific paths and directories we want it to look over.

pycodestyle

pycodestyle is a tool that checks our Python code against some of the styling conventions outlined in the PEP 8 style guide. The pycodestyle library doesn’t check everything. For example, it currently doesn’t support checks for naming conventions, docstring conventions, or automatic fixing. There are different extensions and tools that are available that can check some of the things that pycodestyle can’t check.

Autoformatters

Autoformatters refactor our Python code to comply with the PEP 8 style guide. Autoformatters aren’t usually as strict as linters. For example, a solid linter will let us know when our code is too complex, but an autoformatter won’t. If we have an inappropriate variable name, an autoformatter won’t flag that for us. An autoformatter will make our code a bit prettier, but it won’t necessarily ensure we write readable and correct code. Let’s take a look at two popular autoformatters:

autopep8

autopep8 is a tool that formats Python code based on the PEP 8 style guide. A tool like autopep8 will help you write consistent and readable code without putting too much extra time and effort into it yourself! Here are a couple of ways we can install autopep8:

pip install:

pip install --upgrade autopep8
Enter fullscreen mode Exit fullscreen mode

easy_install:

easy_install -ZU autopep8
Enter fullscreen mode Exit fullscreen mode

Let’s take a look at an example implementation of autopep8 on some simple Python code:

Before autopep8:

import sys, os;
print(                 "hello"       );
Enter fullscreen mode Exit fullscreen mode

After autopep8:

import sys
import os
print("hello")
Enter fullscreen mode Exit fullscreen mode

Black

Black helps take care of minor stylistic and structural issues so we can focus on bigger coding problems. We can install it by running pip install black. If you want to use it, make sure you have Python 3.60+ otherwise it won’t run. Once Black installs, we can use it as a command-line tool right away.

Wrapping up and next steps

The PEP 8 style guide makes reading and writing code a lot more effective and efficient. While the guide may not always apply to our work, it’s a useful tool that we can use to elevate our code reading and writing processes. We only covered a small portion of PEP 8 in this article, and there’s still so much to learn. Some recommended topics to cover next include:

  • Hanging indents
  • Formatting if statements
  • Lambda
  • And much more

To get started with Python programming, check out Educative’s path Python for Programmers. This curated learning path will help you use your programming experience to get comfortable with Python. By the end, you’ll have the advanced knowledge you need to confidently use Python in your next project.

Happy learning!

Continue reading about the Python programming language

Discussion (0)