Python Coding Standards

Python Coding Standards

For python projects we will follow the python PEP 8 – Style Guide for Python Code this is the standard most python code should follow.

To aid in this there are a number of tools to make life easier.

  • ruff is my recommendation as it combines format and checks (basically combining the tools below)
  • black is very common for code formatting
  • isort will sort imports
  • autopep8 automatically formats Python code to conform to the PEP 8 style guide

Most of these tools will format the code based on the details below.

A Foolish Consistency is the Hobgoblin of Little Minds

One of Guido’s key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, “Readability counts”.

Whilst these guideline help in many ways (for example when staff see you code for the first time it reduces the “wtf per minute”) use tools to format and don’t waste lots of time doing it yourself, follow the core rules of the naming conventions / spacing the tools will do the rest.

Code Layout Basics

The following basic rules should be applied where possible

  • Indentation: 4 spaces per level (never tabs).
  • Line length: Max 88 characters (PEP 8 says 79!) ruff can update to more.
  • Blank lines:
    • 2 lines before top-level functions and classes.
    • 1 line between methods inside a class.
  • Imports:
    • Standard library first, then third-party, then local imports.
    • Each group separated by a blank line.

Naming Conventions

  • Variables & functions: lowercase_with_underscores
  • Classes: CamelCase
  • Constants: ALL_CAPS
  • Private (internal use): _leading_underscore

Whitespace Rules

  • Around operators: x = y + 2 not x=y+2.
  • After commas: my_list = [1, 2, 3].
  • No spaces inside parentheses/brackets: func(x, y) not func( x , y ).

Strings & Quotes

  • Single (’) or double (") quotes are fine, just be consistent.
  • Triple quotes ("""docstring""") for docstrings.

Docstrings & Comments

  • Docstrings: Explain what a function/class/module does.
  • Inline comments: Use sparingly, only when code isn’t obvious.
  • Start comments with a capital letter, use full sentences.
  • Use type hints whenever possible
def vec3_add(a : float , b : float ) -> vec3:
    """Return the element-wise sum of two 3D vectors."""
    return vec3(a.x + b.x,a.y + b.y,a.z + b.z)

General

  • Don’t compare to True/False directly:
if is_ready:  # ✅
if is_ready == True:  # ❌
  • Use is None / is not None, avoid == None.
  • Avoid wildcard imports (from module import *)

pre-commit hooks

It is also possible to setup a git pre-commit hook to ensure your code passes before it is uploaded to a repository.

This is the setup I use for most of my projects

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    # Ruff version.
    rev: v0.12.10
    hooks:
      # Run the linter.
      - id: ruff-check
        types_or: [python, pyi]
        args: ["check", "--select", "I", "--fix"]
      # Run the formatter.
      - id: ruff-format
        types_or: [python, pyi]

#noqa

When you add # noqa to the end of a line, it tells the linter “Ignore linting errors on this line.”

For example we can use # noqa F403 to ignore the import * rule

from mymodule import *  # noqa: F403

This should only be used in limited cases where appropriate, and your should really fix your code. If you must ignore errors document why you’re ignoring so others can understand.

uv

You should use uv for all project setup over pip, pyproject.toml and uv.lock files should be included in any repositories.

If using multiple folders / projects a uv workspace should be used and the general uv projects guidelines should be followed.

Next