Coding Conventions
Python Coding Conventions
The rules are almost identical to those used by the Docutils project:
Attention
Contributed code will not be refused merely because it does not strictly adhere to these conditions; as long as it’s internally consistent, clean, and correct, it probably will be accepted. But don’t be surprised if the “offending” code gets fiddled over time to conform to these conventions.
The project follows the generic coding conventions as specified in the Style Guide for Python Code and Docstring Conventions PEPs, clarified and extended as follows:
Use
'single quotes'for string literals, and"""triple double quotes"""for docstrings. Double quotes are OK for something like"don't".No trailing commas.
No hanging end-parenthesis.
Do not use “
*” imports such asfrom module import *. Instead, list imports explicitly.Use 4 spaces per indentation level. No tabs.
Read the Whitespace in Expressions and Statements section of PEP8.
Avoid trailing whitespaces.
No one-liner compound statements (i.e., no
if x: return: use two lines).Maximum line length is 78 characters.
Use “StudlyCaps” for class names.
Use “lowercase” or “lowercase_with_underscores” for function, method, and variable names. For short names, joined lowercase may be used (e.g. “tagname”). Choose what is most readable.
No single-character variable names, except indices in loops that encompass a very small number of lines (
for i in range(5): ...).Avoid lambda expressions. Use named functions instead.
Avoid functional constructs (filter, map, etc.). Use list comprehensions instead.
Example:
# Copyright (C) 2008 CAMd
# Please see the accompanying LICENSE file for further information.
"""This module is an example of good coding style.
This docstring should begin with a one-line description followed by a
blank line, and then this paragraph describing in more words what kind
of functionality this module implements.
After this docstring we have import statements in this order:
1. From the Python standard library.
2. Other libraries (numpy, ase, ...).
3. GPAW stuff.
"""
from math import pi
import numpy as np
from ase.units import Ha
from gpaw import debug
import gpaw.mpi as mpi
# Use upper case for constants:
CONSTANT = [
'A',
'B',
'C'] # notice: no trailing comma and no hanging end-parenthesis!
class SimpleExample:
"""A simple example class.
A headline, a blank line and then this longer description of the
class.
Here one could put an example of how to use the class::
ex = SimpleExample('Test', (2, 3), int, verbose=False)
ex.run(7, verbose=True)
"""
def __init__(self, name, shape, dtype=float, verbose=True):
"""Create an example object.
Again, headline, blank line, ... . If there are many
parameters, there should be a parameter section (see below).
If there only a few possible arguments, then the parameter
section can be left out and the arguments can be described in
the section following the headline and blank line (see the
`run` method). If a method is real simple and
self-explanatory, the docstring can be the headline only (see
the `reset` method).
Parameters:
name : string
Name of the example.
shape: tuple
Shape of the ndarray.
dtype: ndarray datatype
The datatype of the ndarray. Here, the description can go
on to a second line if needed. Make sure that the
indentation is like shown here, and remember to end with a
period.
verbose: boolean
Print information about this and that.
Other sections:
There can be other sections - see bolow and here:
https://scipy.org/...
"""
self.name = name
if verbose:
print(name)
self.a = np.zeros(shape, dtype)
self.verbose = verbose
def method_with_long_name(self, b, out=None):
"""Do something very complicated.
Long story with all details here ...
Parameters:
b: ndarray
Add this array.
out: ndarray
Optional output array.
Returns:
The sum of ...
"""
if out is None:
return self.a + b
else:
return np.add(self.a, b, out)
def run(self, n):
"""Do something.
Do it n times, where n must be a positive integer. The final
result bla-bla is returned.
"""
for i in range(n):
self.a += i
if self.verbose:
print(self.a)
return pi * self.a / n + 1
def reset(self):
"""Simple method - no explanation needed."""
self.a[:] = 0
def function(a, b):
"""Headline.
Long story ..."""
result = a + b
if debug and mpi.world.rank == 0:
print(result * Ha)
return result
General advice
Get rid of as many
breakandcontinuestatements as possible.Write short functions. All functions should fit within a standard screen.
Use descriptive variable names.
Writing documentation in the code
ASE follows the NumPy/SciPy convention for docstrings:
C-code
Code C in the C99 style:
for (int i = 0; i < 3; i++) {
double f = 0.5;
a[i] = 0.0;
b[i + 1] = f * i;
}
and try to follow PEP7.
Use M-x c++-mode in emacs.