https://www.python.org/dev/peps/pep-0008/#pet-peeves
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)
Wrong:
# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
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.
Limiting the required editor window width makes it possible to have several files open side by side, and works well when using code review tools that present the two versions in adjacent columns.
The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation.
Imports should usually be on separate lines:
Correct:
import os
import sys
from subprocess import Popen, PIPE
Wrong:
import sys, os
Imports should be grouped in the following order:
- Standard library imports.
- Related third party imports.
- Local application/library specific imports.
You should put a blank line between each group of imports.
Absolute imports are recommended, as they are usually more readable and tend to be better behaved if the import system is incorrectly configured:
Correct:
# Standard library imports
import os
import sys
from subprocess import Popen, PIPE
# Related third party imports
import pandas as pd
import numpy as np
# Local application/library specific imports.
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
Wildcard imports should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.
Correct:
from pycaret import classification
from pycaret import regression
Wrong:
from pycaret.classification import *
from pycaret.regression import *
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
In Python, single-quoted strings and double-quoted strings are the same. This PEP does not make a recommendation for this. Pick a rule and stick to it. When a string contains single or double quote characters, however, use the other one to avoid backslashes in the string. It improves readability.
For triple-quoted strings, always use double quote characters to be consistent with the docstring convention in PEP 257.
Correct:
product_list = ["carro", "moto", "etc."]
product_list = ['carro', 'moto', 'etc.']
Wrong:
product_list = ["carro", 'moto', "bike", 'etc.']
Avoid extraneous whitespace in the following situations:
Correct:
spam(ham[1], {eggs: 2})
foo = (0,)
if x == 4:
print(x, y)
x, y = y, x
spam(1)
def complex(real, imag=0.0):
return magic(r=real, i=imag)
def munge(sep: AnyStr = None):
Wrong:
spam( ham[ 1 ], { eggs: 2 } )
bar = (0, )
if x == 4 :
print (x , y )
x , y = y , x
spam (1)
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
def munge(input: AnyStr=None):
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!
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
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. This comment should appear after the def line.
One-line Docstrings:
def kos_root():
"""Return the pathname of the KOS root directory."""
global _kos_root
if _kos_root:
return _kos_root
...
Multi-line Docstrings:
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...
Class names should normally use the CapWords convention.
Because exceptions should be classes, the class naming convention applies here. However, you should use the suffix "Error" on your exception names (if the exception actually is an error).
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
Variable names follow the same convention as function names.
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW and TOTAL.
SAMPLE_RATE = 0.7
class StoreAI:
def __init__(self):
pass
def train_model(input_features: pd.DataFrame):
input_features.sample(frac=SAMPLE_RATE)
...
Use is not operator rather than not ... is. While both expressions are functionally identical, the former is more readable and preferred:
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
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)
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 compare boolean values to True or False using ==:
Correct:
if greeting:
Wrong:
if greeting == True:
if greeting is True: