Beautiful Python Code with PEP 8
Source: How to Write Beautiful Python Code With PEP 8
Naming Conventions
“Explicit is better than implicit.” — The Zen of Python
‼️ Note: Never use l (\ell), O (zero), or I (capital i) single letter names as these can be mistaken for 1 and 0, depending on typeface:
Naming styles
How to choose names
The best way to name your objects in Python is to use descriptive names to make it clear what the object represents.
Always try to use the most concise but descriptive names possible.
❌
# Not recommended
>>> x = 'John Smith'
>>> y, z = x.split()
>>> print(z, y, sep=', ')
'Smith, John'
✅
>>> # Recommended
>>> name = 'John Smith'
>>> first_name, last_name = name.split()
>>> print(last_name, first_name, sep=', ')
'Smith, John'
Code Layout
“Beautiful is better than ugly.” — The Zen of Python
Blank lines
Surround top-level functions and classes with two blank lines
Example:
class MyFirstClass:
pass
class MySecondClass:
pass
def top_level_function():
return None
Surround method definitions inside classes with a single blank line.
Example:
def first_method(self):
return None
def second_method(self):
return None
Use blank lines sparingly inside functions to show clear steps.
Example:
def calculate_variance(number_list):
sum_list = 0
for number in number_list:
sum_list = sum_list + number
mean = sum_list / len(number_list)
sum_squares = 0
for number in number_list:
sum_squares = sum_squares + number**2
mean_squares = sum_squares / len(number_list)
return mean_squares - mean**2
Maximum Line Length and Line Breaking
Lines should be limited to 79 characters.
Outlines ways to allow statements to run over several lines:
-
Assume line continuation if code is contained within parentheses, brackets, or braces:
def function(arg_one, arg_two, arg_three, arg_four): return arg_one
-
Use backslashes to break lines if it is impossible to use implied continuation:
from mypkg import example1, \\ example2, example3
-
if you can use implied continuation, then you should do so.
-
If line breaking needs to occur around binary operators, like + and *, it should occur before the operator
❌
# Not Recommended total = (first_variable + second_variable - third_variable)
✅
# Recommended total = (first_variable + second_variable - third_variable)
-
Indentation
- Use 4 consecutive spaces to indicate indentation.
- Prefer spaces over tabs.
Indentation Following Line Breaks
When you’re using line continuations to keep lines to under 79 characters, it is useful to use indentation to improve readability. It allows the reader to distinguish between two lines of code and a single line of code that spans two lines.
There are two styles of indentation you can use:
-
align the indented block with the opening delimiter:
def function(arg_one, arg_two, arg_three, arg_four): return arg_one
Sometimes only 4 spaces are needed to align with the opening delimiter. This will often occur in if statements that span multiple lines as the
if
, space, and opening bracket make up 4 characters. In this case, it can be difficult to determine where the nested code block inside the if statement begins:Example:
x = 5 if (x > 3 and x < 10): print(x)
In this case, PEP 8 provides two alternatives to help improve readability:
-
Add a comment after the final condition.
x = 5 if (x > 3 and x < 10): # Both conditions satisfied print(x)
-
Add extra indentation on the line continuation:
x = 5 if (x > 3 and x < 10): print(x)
-
-
hanging indent: You can use a hanging indent to visually represent a continuation of a line of code.
Example:
var = function( arg_one, arg_two, arg_three, arg_four)
‼️ When you’re using a hanging indent, there must not be any arguments on the first line. The following example is not PEP 8 compliant:
var = function(arg_one, arg_two, arg_three, arg_four)
-
When using a hanging indent, add extra indentation to distinguish the continued line from code contained inside the function.
❌
# Not Recommended def function( arg_one, arg_two, arg_three, arg_four): return arg_one
Instead, it’s better to use a double indent on the line continuation. This helps you to distinguish between function arguments and the function body, improving readability:
✅
# Recommended def function( arg_one, arg_two, arg_three, arg_four): return arg_one
-
Where to Put the Closing Brace
Two options for the position of the closing brace in implied line continuations:
-
Line up the closing brace with the first non-whitespace character of the previous line:
list_of_numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
-
Line up the closing brace with the first character of the line that starts the construct:
list_of_numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Consistency is key, try to stick to one of the above methods.
Comments and Documentations
Whitespace in Expressions and Statements
“Sparse is better than dense.”— The Zen of Python
Whitespace Around Binary Operators
Surround the following binary operators with a single space on either side:
- Assignment operators (
=
,+=
,-=
, and so forth) - Comparisons (
==
,!=
,>
,<
.>=
,<=
) and (is
,is not
,in
,not in
) - Booleans (
and
,not
,or
)
‼️ Note:
-
When
=
is used to assign a default value to a function argument, do NOT surround it with spaces.✅
# Recommended def function(default_parameter=5): # ...
❌
# Not recommended def function(default_parameter = 5): # ...
-
If there’s more than one operator in a statement, only add whitespace around the operators with the lowest priority. especially when performing mathematical manipulation.
✅
# Recommended y = x**2 + 5 z = (x+y) * (x-y)
❌
# Not recommended y = x ** 2 + 5 z = (x + y) * (x - y)
-
Apply this rule to
if
statements where there are multiple conditions:✅
# Recommended if x>5 and x%2==0: print('x is larger than 5 and divisible by 2!')
❌
# Not recommended if x > 5 and x % 2 == 0: print('x is larger than 5 and divisible by 2!')
-
In slices, colons act as a binary operators. Therefore, the rules outlined in the previous section apply, and there should be the same amount of whitespace either side. The following examples of list slices are valid:
list[3:4] # Treat the colon as the operator with lowest priority list[x+1 : x+2] # In an extended slice, both colons must be # surrounded by the same amount of whitespace list[3:4:5] list[x+1 : x+2 : x+3] # The space is omitted if a slice parameter is omitted list[x+1 : x+2 :]
-
Summary
Surround most operator with whitespace, except:
- in function arguments
- combining multiple operators in one statement
Programming Recommendations
“Simple is better than complex.”— The Zen of Python
🎯 Goal: readability and simplicity
Don’t compare boolean values to True
or False
using the equivalence operator.
❌
# Not recommended
my_bool = 6 > 5
if my_bool == True:
return '6 is bigger than 5'
✅
# Recommended
if my_bool:
return '6 is bigger than 5'
Use the fact that empty sequences are falsy in if
statements.
In Python any empty list, string, or tuple is falsy.
❌
# Not recommended
my_list = []
if not len(my_list):
print('List is empty!')
✅
# Recommended
my_list = []
if not my_list:
print('List is empty!')
Use is not
rather than not ... is
in if
statements.
❌
# Not recommended
if not x is None:
return 'x exists!'
✅
# Recommended
if x is not None:
return 'x exists!'
Don’t use if x:
when you mean if x is not None:
.
❌
# Not recommended
if arg:
# Do something with arg...
✅
# Recommended
if arg is not None:
# Do something with arg...
Use .startswith()
and .endswith()
instead of slicing.
-
prefix
❌
# Not recommended if word[:3] == 'cat': print('The word starts with "cat"')
✅
# Recommended if word.startswith('cat'): print('The word starts with "cat"')
-
suffix
❌
# Not recommended if file_name[-3:] == 'jpg': print('The file is a JPEG')
✅
# Recommended if file_name.endswith('jpg'): print('The file is a JPEG')
Tips and Tricks to Help Ensure Your Code Follows PEP 8
Never ignore PEP 8!!!
Linters
Linters are programs that analyze code and flag errors. They provide suggestions on how to fix the error.
Best linters for Python code:
-
pycodestyle
is a tool to check your Python code against some of the style conventions in PEP 8.Install
pycodestyle
usingpip
:$ pip install pycodestyle
-
flake8
is a tool that combines a debugger,pyflakes
, withpycodestyle
.Install
flake8
usingpip
:$ pip install flake8
Autoformatters
Autoformatters are programs that refactor your code to conform with PEP 8 automatically. Once such program is
black
, which autoformats code following most of the rules in PEP 8.
Install black
using pip
. It requires Python 3.6+ to run:
$ pip install black