PEP 8 — Style Guide for Python Code
Read my article or go with details documentation in PEP
One of Guido’s key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code.
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important.
Code Lay-out
Indentation
Use 4 spaces per indentation level.
# Correct:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Add 4 spaces (an extra level of indentation) to
# distinguish arguments from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
The 4-space rule is optional for continuation lines.
Optional:
# Hanging indents *may* be indented to other than 4 spaces.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
When the conditional part of an if
-statement is long enough to require that it be written across multiple lines,
# No extra indentation.
if (this_is_one_thing and
that_is_another_thing):
do_something()
# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()
# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
and that_is_another_thing):
do_something()
The closing brace/bracket/parenthesis on multiline constructs may either line up under the first non-whitespace character of the last line of list, as in:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
Maximum Line Length
Limit all lines to a maximum of 79 characters.
For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.
Backslashes may still be appropriate at times. For example, long, multiple
with
-statements could not use implicit continuation before Python 3.10, so backslashes were acceptable for that case:
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
Should a Line Break Before or After a Binary Operator?
# Correct:
# easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
Blank Lines
Surround top-level function and class definitions with two blank lines.
Method definitions inside a class are surrounded by a single blank line.
Extra blank lines may be used (sparingly) to separate groups of related functions.
Imports
- Imports should usually be on separate lines:
# Correct:
import os import sys
# Wrong:
import sys, os
# Its okay to say this though
# Correct:
from subprocess import Popen,PIPE
Module Level Dunder Names
Module level “dunders” (i.e. names with two leading and two trailing underscores) such as __all__
, __author__
, __version__
, etc. should be placed after the module docstring but before any import statements except from __future__
imports. Python mandates that future-imports must appear in the module before any other code except docstrings:
"""This is the example module.
This module does stuff.
"""from __future__ import barry_as_FLUFL__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'import os
import sys
String Quotes
In Python, single-quoted strings and double-quoted strings are the same.
Whitespace in Expressions and Statements
Pet Peeves
Avoid extraneous whitespace in the following situations:
- Immediately inside parentheses, brackets or braces:
# Correct:
spam(ham[1], {eggs: 2})
# Wrong:
spam( ham[ 1 ], { eggs: 2 } )
Between a trailing comma and a following close parenthesis.
# Correct:
foo = (0,)
# Wrong:
bar = (0, )
Immediately before a comma, semicolon, or colon:
# Correct:
if x == 4: print(x, y); x, y = y, x
# Wrong:
if x == 4 : print(x , y) ; x , y = y , x
However, in a slice the colon acts like a binary operator, and should have equal amounts on either side
# Correct:
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
# Wrong:
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : step]
ham[ : upper]
- Immediately before the open parenthesis that starts the argument list of a function call:
# Correct:
spam(1)
# Wrong:
spam (1)
Immediately before the open parenthesis that starts an indexing or slicing:
# Correct:
dct['key'] = lst[index]
# Wrong:
dct ['key'] = lst [index]
More than one space around an assignment (or other) operator to align it with another:
# Correct:
x = 1
y = 2
long_variable = 3
# Wrong:
x = 1
y = 2
long_variable = 3
# Correct:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
# Wrong:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
Function annotations should use the normal rules for colons and always have spaces around the ->
arrow if present.
# Correct:
def munge(input: AnyStr): ...
def munge() -> PosInt: ...
# Wrong:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
Don’t use spaces around the =
sign when used to indicate a keyword argument
# Correct:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# Wrong:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
When combining an argument annotation with a default value, however, do use spaces around the =
sign:
# Correct:
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# Wrong:
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...
Compound statements (multiple statements on the same line) are generally discouraged:
# Correct:
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
Rather not:
# Wrong:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
When to Use Trailing Commas
Trailing commas are usually optional, except they are mandatory when making a tuple of one element. For clarity, it is recommended to surround the latter in (technically redundant) parentheses:
# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',
When trailing commas are redundant, they are often helpful when a version control system is used, when a list of values, arguments or imported items is expected to be extended over time.
# Correct:
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
Comments
Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!
Comments should be complete sentences. The first word should be capitalized, unless it is an identifier that begins with a lower case letter
Block Comments use #
Inline Comments
Inline comments are unnecessary and in fact distracting if they state the obvious. Don’t do this:
x = x + 1 # Increment x
But sometimes, this is useful:
x = x + 1 # Compensate for border
Documentation Strings
Conventions for writing good documentation strings (a.k.a. “docstrings”) are immortalized in PEP 257.
Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does.
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
Naming Conventions
Descriptive: Naming Styles
The following naming styles are commonly distinguished:
b
(single lowercase letter)B
(single uppercase letter)lowercase
lower_case_with_underscores
UPPERCASE
UPPER_CASE_WITH_UNDERSCORES
CapitalizedWords
(or CapWords, or CamelCase – so named because of the bumpy look of its letters [4]). This is also sometimes known as StudlyCaps.- Note: When using acronyms in CapWords, capitalize all the letters of the acronym. Thus HTTPServerError is better than HttpServerError.
mixedCase
(differs from CapitalizedWords by initial lowercase character!)Capitalized_Words_With_Underscores
(ugly!)
Names to Avoid
Never use the characters ‘l’ (lowercase letter el), ‘O’ (uppercase letter oh), or ‘I’ (uppercase letter eye) as single character variable names.
Function and Variable Names
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
Variable names follow the same convention as function names.
Function and Method Arguments
Always use self
for the first argument to instance methods.
Always use cls
for the first argument to class methods.
Thus class_
is better than clss
Constants
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW
and TOTAL
..
Programming Recommendations
# Correct:
if foo is not None:
# Wrong:
if not foo is None:
- Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier:
# Correct:
def f(x): return 2*x
# Wrong:
f = lambda x: 2*x
- The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘<lambda>’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)
Additionally, for all try/except clauses, limit the
try
clause to the absolute minimum amount of code necessary. Again, this avoids masking bugs:
# Correct:
try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
# Wrong:
try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
Be consistent in return statements.
# Correct:
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
def bar(x):
if x < 0:
return None
return math.sqrt(x)
# Wrong:
def foo(x):
if x >= 0:
return math.sqrt(x)
def bar(x):
if x < 0:
return
return math.sqrt(x)
- Use
''.startswith()
and''.endswith()
instead of string slicing to check for prefixes or suffixes.
startswith() and endswith() are cleaner and less error prone:
# Correct:
if foo.startswith('bar'):
# Wrong:
if foo[:3] == 'bar':
- Object type comparisons should always use isinstance() instead of comparing types directly:
# Correct:
if isinstance(obj, int):
# Wrong:
if type(obj) is type(1):
- For sequences, (strings, lists, tuples), use the fact that empty sequences are false:
# Correct:
if not seq:
if seq:
# Wrong:
if len(seq):
if not len(seq):
- Don’t write string literals that rely on significant trailing whitespace. Such trailing whitespace is visually indistinguishable and some editors (or more recently, reindent.py) will trim them.
- Don’t compare boolean values to
# Correct:
if greeting
# Wrong:
if greeting == True:
# Wrong:
if greeting is True:
- Use of the flow conttatements
return
/break
/continue
within the finally suite of atry...finally
, where the flow control statement would jump outside the finally suite, is discouraged. This is because such statements will implicitly cancel any active exception that is propagating through the finally suite:
# Wrong:
def foo():
try:
1 / 0
finally:
return 42
Variable Annotations
- Annotations for module level variables, class and instance variables, and local variables should have a single space after the colon.
# Correct:
code: int
class Point:
coords: Tuple[int, int]
label: str = '<unknown>'
# Wrong:
code:int # No space after colon
code : int # Space before colon
class Test:
result: int=0 # No spaces around equality sign