Skip to content
This repository was archived by the owner on Jun 26, 2026. It is now read-only.

Latest commit

 

History

History
177 lines (143 loc) · 7.76 KB

python_standards.md

File metadata and controls

177 lines (143 loc) · 7.76 KB

Python Standards

Style Considerations

Much of these considerations are adapted from the PEP 8 Style Guide for Python

Presentation

Indentation

We should use 4 space indentation in our code. Ensure that your IDE is set up so that indents represent 4 spaces and not tabs. When requiring multiple lines, always align with the opening delimiter.

# Bad:  

foo = long_function_name(var_one, var_two,  
    var_three, var_four)  

my_list = [1, 2, 3,   
    4, 5, 6,]  

# Good:  

foo = long_function_name(var_one, var_two,  
                         var_three, var_four)  

my_list = [1, 2, 3,   
           4, 5, 6,]

Using Line spaces - Sparse is better than dense

  • 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.

Using White spaces

Avoid extraneous whitespace in the following situations:

  • Immediately inside parentheses, brackets or braces
  • Between a trailing comma and a following close parenthesis
  • Immediately before a comma, semicolon, or colon
  • Immediately before the open parenthesis that starts the argument list of a function call
  • Immediately before the open parenthesis that starts an indexing or slicing
  • More than one space around an assignment (or other) operator to align it with another

Some examples below:

# Good:  
spam(ham[1], {eggs: 2})  

# Bad:  
spam( ham[ 1 ], { eggs: 2 } )  

# Good:  
if x == 4: print x, y; x, y = y, x  

# Bad:  
if x == 4 : print x , y ; x , y = y , x  

# Good:  
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]  
ham[lower:upper], ham[lower:upper:], ham[lower::step]  
ham[lower+offset : upper+offset]  
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]  
ham[lower + offset : upper + offset]  

# Bad:  
ham[lower + offset:upper + offset]  
ham[1: 9], ham[1 :9], ham[1:9 :3]  
ham[lower : : upper]  
ham[ : upper]  

# Good:  
spam(1)  

# Bad  
spam (1)  

# Good:  
dct['key'] = lst[index]  

# Bad:  
dct ['key'] = lst [index]  

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

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

Naming

There are many opinions on the best way to name variables in python. We will generally follow the guidelines in PEP 8 - Naming Conventions

Naming conventions

  • Variable names should be no less than 3 characters and should be descriptive of what the variable represents
  • Use CAPITALS to define constants or globals that will be used in your entire program or module
  • Use lowercase_with_underscores for local variables, member attributes or methods, function arguments and parameters
  • Use PascalCase for classes
  • Use short lowercase names for scripts

Global variables and namespaces

In Python, variable lookups go up from local namespace to parent namespace to global namespace. Below, python looks in the local namespace of multiply and cannot find GLOBALVAR so it looks in the parent scope

GLOBALVAR = 12345  

def multiply(x):  
    return x * GLOBALVAR # GLOBALVAR = 12345

If you declare a variable inside a local scope, then it is immediately local unless you use the global keyword (which works at the module level)

GLOBALVAR = 12345  

def multiply(x):  
    GLOBALVAR = 1  
    return x * GLOBALVAR # GLOBALVAR = 1  

def changeGlobal(x):  
    global GLOBALVAR        # GLOBALVAR in this scope references the global GLOBALVAR  
    GLOBALVAR = 5678        # changes GLOBALVAR  
    return x * GLOBALVAR    # GLOBALVAR = 5678  

print(GLOBALVAR)            # prints 12345  
x = multiply(2)             # x = 24690  
print(GLOBALVAR)            # prints 12345  
y = changeGlobal(2)         # y = 11356  
print(GLOBALVAR)            # prints 5678

Documentation

Docstrings

For more info on docstring best practices, see PEP 257.

A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.

All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have docstrings. A package may be documented in the module docstring of the __init__.py file in the package directory.

For consistency, always use """triple double quotes""" around docstrings. Use r"""raw triple double quotes""" if you use any backslashes in your docstrings.

Comments

Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment).

Paragraphs inside a block comment are separated by a line containing a single #.

Use inline comments sparingly. An inline comment is a comment on the same line as a statement. Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.

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

Assertive Programming

Assertive programming is an important way to sanity check around human error and validate inputs for functions. Assert statements are also useful in indicating to someone else exactly how your code should be used. In the below code block, the assert statement forces the function to ensure a valid input amount (greater than 0) before commencing with the function work. If the assert statement fails (refund_amount <= 0), then an assert error will be thrown.

def refund_client(refund_amount):
    assert refund_amount > 0, f"refund amound needs to be positive, this is invalid {refund_amount}"
    now_do_the_actual_work()

Packages