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.