As our dev team grows, I have found that our coding style is a mess (myself included), when doing code review and refactoring. Especially for someone who is new to Python and has no professional dev experience before. I have written a short summary of PEP 8 – Style Guide for Python Code and PEP 257: Docstring Conventions for them to follow. More importantly, everyone must have their code gone through a Code Inspection tool, e.g., the PEP8 package (pip install pep8), pylint, or the Inspect Code function in PyCharm IDE, before creating a pull request.

The following are some of them:

Indentation, line-length & code wrapping

  • Always use 4 spaces for indentation (don’t use tabs)
  • Write in ASCII in Python 2 and UTF-8 in Python 3
  • Max line-length: 80 characters (especially in comments)
  • Always indent wrapped code for readability
# Good:
result = some_function_that_takes_arguments(
    'argument one,
    'argument two',
    'argument three'
)

long_foo_dict_with_many_elements = {
    'foo': 'cat',
    'bar': 'dog'
}

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())

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

# Bad:
result = some_function_that_takes_arguments(
'argument one,
'argument two', 'argument three')
result2 = some_function_that_takes_arguments('argument one', 'argument two', 'argument three')

Imports

  • Don’t use wildcards
  • Import standard libs first, 3rd-party libs next, and local stuff last
  • Try to import in a alphabetical order
  • Try to use absolute imports over relative ones
  • When using relative imports, be explicit (with .)
  • Don’t import multiple packages per line
# Good:
import os # STD lib imports first
import sys # alphabetical

from mypkg.sibling import example # 3rd party stuff next
from subprocess import Popen, PIPE # Acceptable

from .sibling import example # local stuff last

# Bad:
import os, sys # multiple packages
import sibling # local module without "."
from mypkg import * # wildcards

Whitespace and newlines

  • 2 blank lines before top-level function and class definitions
  • 1 blank line before class method definitions
  • Use blank lines in functions sparingly
  • Avoid extraneous whitespace
  • Don’t use whitespace to line up assignment operators (=, :)
  • Spaces around = for assignment
  • No spaces around = for default parameter values
  • Spaces around mathematical operators, but group them sensibly
  • Multiple statements on the same line are discouraged
# Good:
spam(ham[1], {eggs: 2})

if x == 4:
    print x, y
    x, y = y, x
dict['key'] = list[index]

y = 2
long_variable = 3
hypot2 = x*x + y*y
c = (a+b) * (a-b)

def complex(real, imag=0.0):
    return magic(r=real, i=imag)

do_one()
do_two()

# Bad
spam ( ham[ 1 ], { eggs: 2 } ) # spaces inside brackets
if x == 4 : print x , y ; x , y = y , x # inline statements, space before commas
dict ['key'] = list [index] # space before dictionary key
y             = 2 # Using spaces to line up assignment operators
long_variable = 3
hypot2 = x * x + y * y # Too much space around operators
c = (a + b) * (a - b) # Too much space around operators

def complex(real, imag = 0.0):
    return magic(r = real, i = imag) # Spaces in default values

Comments

  • Keep comments up to date - incorrect comments are worse than no comments
  • Write in whole sentences
  • Try to write in plain and easy-to-follow English
  • Use inline comments sparingly & avoid obvious comments
  • Each line of block comments should start with #
  • Paragraphs in block comments should be separated by a line with a single #
  • All public functions, classes and methods should have docstrings
  • Docstrings should start and end with """
  • Docstring one-liners can be all on the same line
  • In docstrings, list each argument on a separate line
  • Docstrings should have a blank line before the final """
def my_function():
    """ A one-line docstring """

def my_other_function(parameter=False):
    """
    A multiline docstring.

    Keyword arguments:
    parameter -- an example parameter (default False)

    """

Naming conventions

  • Class names in CapWords
  • Method, function and variables names in lowercase_with_underscores
  • Private methods and properties start with __double_underscore
  • “Protected” methods and properties start with _single_underscore
  • If you need to use a reserved word, add a _ to the end (e.g. class_)
  • Use all-uppercase FIXED_TERM for constant variables
  • Always use self for the first argument to instance methods
  • Always use cls for the first argument to class methods
  • Never declare functions using lambda (f = lambda x: 2*x)
A_CONSTANT = 'ugh.'

class MyClass:
    """ A purely illustrative class """

    __property = None

    def __init__(self, property_value):
        self.__property = property_value

    def get_property(self):
        """ A simple getter for "property" """

        return self.__property

    @classmethod
    def default(cls):
        instance = MyClass("default value")
        return instance

The styles above are the critical ones for a clean and styled code. As always, some extra rules can be defined to suit your needs.

References