|
|
|
# Purpose
|
|
|
|
|
|
|
|
This documents aims at defining standard coding rules for all Python code in the application. It is based on \[PEP 8\](<https://www.python.org/dev/peps/pep-0008/>).
|
|
|
|
|
|
|
|
## Code Lay-out
|
|
|
|
|
|
|
|
Use 4 spaces per indentation level.
|
|
|
|
|
|
|
|
Continuation lines should align wrapped elements either vertically using Python's implicit line joining inside parentheses, brackets and braces, or using a _hanging indent_
|
|
|
|
|
|
|
|
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)`
|
|
|
|
|
|
|
|
The 4-space rule is optional for continuation lines.
|
|
|
|
|
|
|
|
The closing brace/bracket/parenthesis on multiline constructs may either line up under the first non-whitespace character of the last line of list, as in:
|
|
|
|
|
|
|
|
`my_list = [`
|
|
|
|
|
|
|
|
` 1, 2, 3,`
|
|
|
|
|
|
|
|
` 4, 5, 6,`
|
|
|
|
|
|
|
|
` ]`
|
|
|
|
|
|
|
|
`result = some_function_that_takes_arguments(`
|
|
|
|
|
|
|
|
` 'a', 'b', 'c',`
|
|
|
|
|
|
|
|
` 'd', 'e', 'f',`
|
|
|
|
|
|
|
|
` )`
|
|
|
|
|
|
|
|
or it may be lined up under the first character of the line that starts the multiline construct, as in:
|
|
|
|
|
|
|
|
`my_list = [`
|
|
|
|
|
|
|
|
` 1, 2, 3,`
|
|
|
|
|
|
|
|
` 4, 5, 6,`
|
|
|
|
|
|
|
|
`]`
|
|
|
|
|
|
|
|
`result = some_function_that_takes_arguments(`
|
|
|
|
|
|
|
|
` 'a', 'b', 'c',`
|
|
|
|
|
|
|
|
` 'd', 'e', 'f',`
|
|
|
|
|
|
|
|
`)`
|
|
|
|
|
|
|
|
### Maximum Line Length
|
|
|
|
|
|
|
|
Limit all lines to a maximum of 99 characters.
|
|
|
|
|
|
|
|
For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 75 characters.
|
|
|
|
|
|
|
|
### A Line Should Break Before a Binary Operator?
|
|
|
|
|
|
|
|
`# easy to match operators with operands`
|
|
|
|
|
|
|
|
`income = (gross_wages`
|
|
|
|
|
|
|
|
` + taxable_interest`
|
|
|
|
|
|
|
|
` + (dividends - qualified_dividends)`
|
|
|
|
|
|
|
|
` - ira_deduction`
|
|
|
|
|
|
|
|
` - student_loan_interest)`
|
|
|
|
|
|
|
|
### Blank lines
|
|
|
|
|
|
|
|
Surround top-level function and class definitions with two blank lines.
|
|
|
|
|
|
|
|
Method definitions inside a class are surrounded by a single blank line.
|
|
|
|
|
|
|
|
Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).
|
|
|
|
|
|
|
|
Use blank lines in functions, sparingly, to indicate logical sections.
|
|
|
|
|
|
|
|
### Imports
|
|
|
|
|
|
|
|
Imports should usually be on separate lines:
|
|
|
|
|
|
|
|
`import os`
|
|
|
|
|
|
|
|
`import sys`
|
|
|
|
|
|
|
|
`from subprocess import Popen, PIPE`
|
|
|
|
|
|
|
|
Wrong :
|
|
|
|
|
|
|
|
`import sys, os`
|
|
|
|
|
|
|
|
Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.
|
|
|
|
|
|
|
|
Imports should be grouped in the following order:
|
|
|
|
|
|
|
|
1. Standard library imports.
|
|
|
|
2. Related third party imports.
|
|
|
|
3. Local application/library specific imports.
|
|
|
|
|
|
|
|
You should put a blank line between each group of imports.
|
|
|
|
|
|
|
|
Wildcard imports (from <module> import \*) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.
|
|
|
|
|
|
|
|
## Whitespace in Expressions and Statements
|
|
|
|
|
|
|
|
Avoid trailing whitespace anywhere. Because it's usually invisible, it can be confusing: e.g. a backslash followed by a space and a newline does not count as a line continuation marker. Some editors don't preserve it and many projects (like CPython itself) have pre-commit hooks that reject it.
|
|
|
|
|
|
|
|
Always surround these binary operators with a single space on either side: assignment (=), augmented assignment (+=, <span dir="">-=</span> etc.), comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), Booleans (and, or, not).
|
|
|
|
|
|
|
|
If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator:
|
|
|
|
|
|
|
|
Correct :
|
|
|
|
|
|
|
|
`i = i + 1`
|
|
|
|
|
|
|
|
`submitted += 1`
|
|
|
|
|
|
|
|
`x = x*2 - 1`
|
|
|
|
|
|
|
|
`hypot2 = x*x + y*y`
|
|
|
|
|
|
|
|
`c = (a+b) * (a-b)`
|
|
|
|
|
|
|
|
Wrong :
|
|
|
|
|
|
|
|
`i=i+1`
|
|
|
|
|
|
|
|
`submitted +=1`
|
|
|
|
|
|
|
|
`x = x * 2 - 1`
|
|
|
|
|
|
|
|
`hypot2 = x x + y y`
|
|
|
|
|
|
|
|
`c = (a + b) * (a - b)`
|
|
|
|
|
|
|
|
Function annotations should use the normal rules for colons and always have spaces around the <span dir="">-></span> arrow if present
|
|
|
|
|
|
|
|
`def munge(input: AnyStr): ...`
|
|
|
|
|
|
|
|
`def munge() -> PosInt: ...`
|
|
|
|
|
|
|
|
Multiple statements on the same line) are generally discouraged
|
|
|
|
|
|
|
|
## Comments
|
|
|
|
|
|
|
|
Comments should be complete sentences. The first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).
|
|
|
|
|
|
|
|
Block comments generally consist of one or more paragraphs built out of complete sentences, with each sentence ending in a period.
|
|
|
|
|
|
|
|
## Documentation Strings
|
|
|
|
|
|
|
|
The documentation will follow the (numpy convention )\[<https://numpydoc.readthedocs.io/en/latest/format.html>\].
|
|
|
|
|
|
|
|
### Sections
|
|
|
|
|
|
|
|
#### Short summary
|
|
|
|
|
|
|
|
A one-line summary that does not use variable names or the function name, e.g.
|
|
|
|
|
|
|
|
`def add(a, b):`
|
|
|
|
|
|
|
|
` """The sum of two numbers.`
|
|
|
|
|
|
|
|
` """`
|
|
|
|
|
|
|
|
#### Extended Summary
|
|
|
|
|
|
|
|
A few sentences giving an extended description. This section should be used to clarify _functionality_, not to discuss implementation detail or background theory, which should rather be explored in the [<span dir="">Notes</span>](https://numpydoc.readthedocs.io/en/latest/format.html#notes) section below. You may refer to the parameters and the function name, but parameter descriptions still belong in the [<span dir="">Parameters</span>](https://numpydoc.readthedocs.io/en/latest/format.html#params) section.
|
|
|
|
|
|
|
|
#### Parameters
|
|
|
|
|
|
|
|
Description of the function arguments, keywords and their respective types.
|
|
|
|
|
|
|
|
`Parameters`
|
|
|
|
|
|
|
|
`----------`
|
|
|
|
|
|
|
|
`x : type`
|
|
|
|
|
|
|
|
` Description of parameter x.`
|
|
|
|
|
|
|
|
`y`
|
|
|
|
|
|
|
|
` Description of parameter y (with type not specified).`
|
|
|
|
|
|
|
|
Enclose variables in single backticks. The colon must be preceded by a space, or omitted if the type is absent.
|
|
|
|
|
|
|
|
For the parameter types, be as precise as possible. Below are a few examples of parameters and their types.
|
|
|
|
|
|
|
|
`Parameters`
|
|
|
|
|
|
|
|
`----------`
|
|
|
|
|
|
|
|
`filename : str`
|
|
|
|
|
|
|
|
`copy : bool`
|
|
|
|
|
|
|
|
`dtype : data-type`
|
|
|
|
|
|
|
|
`iterable : iterable object`
|
|
|
|
|
|
|
|
`shape : int or tuple of int`
|
|
|
|
|
|
|
|
`files : list of str`
|
|
|
|
|
|
|
|
If it is not necessary to specify a keyword argument, use optional :
|
|
|
|
|
|
|
|
`x : int, optional`
|
|
|
|
|
|
|
|
#### Returns
|
|
|
|
|
|
|
|
Explanation of the returned values and their types. Similar to the [<span dir="">Parameters</span>](https://numpydoc.readthedocs.io/en/latest/format.html#params) section, except the name of each return value is optional. The type of each return value is always required:
|
|
|
|
|
|
|
|
`Returns`
|
|
|
|
|
|
|
|
`-------`
|
|
|
|
|
|
|
|
`int`
|
|
|
|
|
|
|
|
` Description of anonymous integer return value.`
|
|
|
|
|
|
|
|
#### Yields
|
|
|
|
|
|
|
|
Explanation of the yielded values and their types. This is relevant to generators only. Similar to the [<span dir="">Returns</span>](https://numpydoc.readthedocs.io/en/latest/format.html#returns) section in that the name of each value is optional, but the type of each value is always required:
|
|
|
|
|
|
|
|
`Yields`
|
|
|
|
|
|
|
|
`------`
|
|
|
|
|
|
|
|
`int`
|
|
|
|
|
|
|
|
` Description of the anonymous integer return value.`
|
|
|
|
|
|
|
|
####
|
|
|
|
|
|
|
|
#### Notes
|
|
|
|
|
|
|
|
An optional section that provides additional information about the code, possibly including a discussion of the algorithm.
|
|
|
|
|
|
|
|
`Notes`
|
|
|
|
|
|
|
|
`-----`
|
|
|
|
|
|
|
|
`The FFT is a fast implementation of the discrete Fourier transform`
|
|
|
|
|
|
|
|
#### Hinting
|
|
|
|
|
|
|
|
All function parameters and returned values types should be hinted :
|
|
|
|
|
|
|
|
`def greeting(name: str) -> str:`
|
|
|
|
|
|
|
|
` return 'Hello ' + name`
|
|
|
|
|
|
|
|
### Documenting classes
|
|
|
|
|
|
|
|
Use the same sections as outlined above (all except Returns are applicable). The constructor (__init__) should also be documented here, the Parameters section of the docstring details the constructor’s parameters.
|
|
|
|
|
|
|
|
An Attributes section, located below the Parameters section, may be used to describe non-method attributes of the class:
|
|
|
|
|
|
|
|
`An AtAttributes`
|
|
|
|
|
|
|
|
`----------`
|
|
|
|
|
|
|
|
`x : float`
|
|
|
|
|
|
|
|
` The X coordinate.`
|
|
|
|
|
|
|
|
`y : float`
|
|
|
|
|
|
|
|
` The Y coordinate.`
|
|
|
|
|
|
|
|
## Naming Conventions
|
|
|
|
|
|
|
|
### Package and Module Names
|
|
|
|
|
|
|
|
Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
|
|
|
|
|
|
|
|
### Class Names
|
|
|
|
|
|
|
|
Class names should normally use the CapWords convention.
|
|
|
|
|
|
|
|
### Function and Variable Names
|
|
|
|
|
|
|
|
Function names should be mixedCase.
|
|
|
|
|
|
|
|
### Method Names and Instance Variables
|
|
|
|
|
|
|
|
Method names and instance variables should be mixedCase.
|
|
|
|
|
|
|
|
### Constants
|
|
|
|
|
|
|
|
Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW and TOTAL.
|
|
|
|
|
|
|
|
## Programming Recommendations
|
|
|
|
|
|
|
|
* Comparisons to singletons like None should always be done with is or is not, never the equality operators.
|
|
|
|
* 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`
|
|
|
|
|
|
|
|
* Use <span dir="">''.startswith()</span> and <span dir="">''.endswith()</span> instead of string slicing to check for prefixes or suffixes.
|
|
|
|
* Don't compare boolean values to True or False using == or is False/ is True
|
|
|
|
|
|
|
|
`# Correct:`
|
|
|
|
|
|
|
|
`if greeting:` |
|
|
|
\ No newline at end of file |