PEP 8 Tutorial: How to Write Readable Code
Make your code clearer and more readable with Python's very own style guide.
Hey Grokking Python readers!
Writing code is an inherently collaborative process. Many different engineers may read the same code over the course of a development process. As a result, it makes sense to spend some extra time writing code to make sure it’s readable and consistent. This is where style guides come in. Style guides help standardize naming conventions and other best practices that help you write consistent and coherent code.
"Code is read much more often than it is written." - Guido van Rossum, the creator of Python
A Python Enhancement Protocol, or PEP, is a document that provides information about proposed changes. PEPs convey information to the Python community and serve as archives for the history of changes made to the language. Today, we're focusing on PEP 8: Python's in house style-guide for writing readable code.
PEP 8 was originally written in 2001 by Python systems' architects, Guido van Rossum, Barry Warsaw, and Nick Coghlan. PEP 8 has largely stood the test of time, only receiving minor changes over the years. Learning a long-standing style guide ensures that your code will consistently meet readability standards for years to come. That said, PEP 8 is not an unfaltering guide and should not be used in every case. Rely on your own judgment for when to stray from it. For example, you should not break backwards compatibility just to comply with PEP 8.
This week, we'll cover some of the PEP 8 fundamentals:
Naming conventions
Code layout
Comments
Linters and autoformatters
PEP 8 naming conventions
Naming conventions improve readability and speed up development time since you don’t have to spend time debating what to name variables, methods, classes, or functions.
Choosing appropriate names when writing code will save time and effort in the long run. In the table below, we outline some of the naming conventions in Python:
It’s important to be mindful of the names you’re choosing to make sure they’re clear, appropriate, and effective. Choosing descriptive names will help out in the long run. If you use a vague name for one of your functions, you, or someone else, may revisit the code in a few days or weeks and not know what it means.
PEP 8 code layout
Whitespace
Vertical whitespace improves the readability of 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)
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 })
Between trailing commas and a follow close parentheses
# Do this: foo = (1,) # Not this: foo = (1, )
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
Right before an open parenthesis that starts the argument list of a function call
# Do this: dog(1) # Not this: dog (1)
Right before an open parenthesis that starts indexing or slicing
# Do this: dct["key'] = lst[index] # Not this: dct ["key"] = lst [index]
More than one space around an operator to align it with another
# Do this: x = 5 y = 10 your_variable = 20 # Not this: x = 5 y = 10 your_variable = 20
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 your code more readable. This way, you can have different files open side by side and 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.
# Do this:
total = (first_variable
+ second_variable
- third_variable)
# Not this:
total = (first_variable +
second_variable -
third_variable)
Indentation
Indentation is very important when writing code in Python. Indentation levels determine how statements are grouped together. Four spaces can be used to represent indentation. The guidelines recommend using spaces instead of tabs.
x = 20
if x > 50:
print("x is greater than 50")
In the above example, the indented print
statement tells Python that it should only execute the statement if the if
statement returns True
.
Spaces are largely the preferred way to indent code. You should only use tabs if you’re working with a piece or section of code that’s already indented using tabs. Python 3 doesn’t allow mixing both tabs and spaces to indent; this means the code won’t run if there are a blend of tabs and spaces. PEP 8 recommends that you use four spaces to indicate an indent.
PEP 8 comments
Comments are an essential part of documenting your code as you go. It’s important to make sure they are clear, up-to-date, and helpful. Not only do comments help you, but they help anyone else that comes into contact with your code. When someone reads your code, the comments should clearly align with the portion of code they describe.
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 your code begins with an identifier, it’s okay to use a lowercase letter here– never change the name of an identifier in any way.
Again, it is a good practice to limit the line length of comments and docstrings to 72 characters.
Let’s take a look at some of the different types of comments and how they fit into PEP 8.
Block comments
Block comments document smaller sections of code. Typically, you'll 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 spaceIndent block comments to the same level as the code they apply to
Separate paragraphs with a line containing a single
#
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, "Tate")
Inline comments
Inline comments document a single statement in a piece of code. They serve to remind 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 spaceDon’t use them to explain anything obvious
Docstrings
Docstrings are string literals that occur as the first line of a class, function, method, or module. You 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 are as follows:
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 multi line 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
Linters
Linters analyze programs and flag errors. Additionally, they give suggestions on how to fix errors. You can install linters as extensions to your code editor or integrated development environment (IDE), which means that they’ll flag errors as you write code.
Let’s take a look at two of the most popular linters:
pycodestyle
Pycodestyle is a tool that checks Python code against some of the styling conventions outlined in the PEP 8 style guide. The pycodestyle
library is not exhaustive in its features though. For example, it currently doesn’t support checks for naming conventions, docstring conventions, or automatic fixing. There are, however, available extensions that support some of these features that pycodestyle doesn't.
Flake8
Flake8 is a tool that combines pyflakes
, pycodestyle
, and a debugger. You can invoke Flake8 on the command line or via Python. Flake8 can check the entire source code, or you can narrow what it checks by indicating specific paths and directories.
Autoformatters
Autoformatters refactor Python code to comply with the PEP 8 style guide. Autoformatters aren’t usually as strict as linters. A solid linter will let you know when your code is too complex, but an autoformatter won’t. For example, if there is an inappropriate variable name, an autoformatter won’t flag it. An autoformatter will make your code a bit prettier, but it won’t necessarily ensure you write readable and correct code.
Two popular Python autoformatters are:
What to learn next about PEP 8
The PEP 8 style guide makes reading and writing code a lot more effective and efficient. While it may not always apply to your work, it’s a useful tool that you can implement to elevate your code reading and writing processes.
We only covered a small portion of PEP 8 in this edition, and there’s still much to learn. Some recommended topics to cover next include:
Hanging indents
Formatting if statements
Lambda
As always, happy learning!