Coding Standards

Last updated on 2026-10-07 | Edit this page

Overview

Questions

  • What tools can help achieve the objectives?

Objectives

  • Enforce uniform style in the code
  • Partially compensate for duck-typing in Python code

Use the following commands if you want to save your work from the previous episode

BASH

$ git add Makefile tests/test_countwords.py
$ git commit -m "my work"

Now use the following to get files for this episode

BASH

$ git switch -c my-05-branch remotes/origin/05-standards
$ git ls-files

which should yield

OUTPUT

Makefile
analyze.py
books/abyss.txt
books/isles.txt
src/TeX/local.bib
src/TeX/report.tex
src/analysis/countwords.py
src/analysis/testzipf.py
src/plotscripts/plotcounts.py
tests/test_countwords.py
tests/test_plotcounts.py
tests/test_testzipf.py

Put this block in the Makefile:

## pylintrc            : Fetch standard from google
pylintrc:
	wget https://google.github.io/styleguide/pylintrc

## lint                : Run pylint
.PHONY : lint
lint : pylintrc
	pylint --rcfile pylintrc src

And run pylint with

BASH

$ make lint

Well, let’s focus on one file

BASH

$ pylint --rcfile pylintrc src/analysis/countwords.py

OUTPUT

************* Module analysis.countwords
src/analysis/countwords.py:32:0: W1405: Quote delimiter " is inconsistent with the rest of the file (inconsistent-quotes)
src/analysis/countwords.py:89:0: W1405: Quote delimiter " is inconsistent with the rest of the file (inconsistent-quotes)
src/analysis/countwords.py:59:12: C0103: Variable name "_tuple" doesn't conform to '^[a-z][a-z0-9_]*$' pattern (invalid-name)

After fixing those let’s try again

BASH

$ make lint

Let’s fix those and try again

BASH

$ make lint

OUTPUT

pylint --rcfile pylintrc src

Check consistency of code style


Callout

YAPF Yet Another Python Formatter

Google AI says

YAPF is an open-source Python code formatter developed by Google. Unlike “opinionated” formatters like Black that enforce a single rigid standard, YAPF uses an algorithm inspired by clang-format to search for the “best” layout matching your specific configuration rules. It works by calculating the “lowest-cost” formatting decision to generate code that looks like an experienced human wrote it.

Let’s use the following block in the Makefile to run yapf

## yapf                : Force google format on all python code
.PHONY : yapf
yapf :
	yapf -i --recursive --style "google" src

In order to see what yapf does let’s first stage the files it might change

BASH

$ git add src
$ git status

Since that looks good, we run yapf

BASH

$ make yapf

OUTPUT

yapf -i --recursive --style "google" src

and check on the changes.

Check Python type hints


By default Python code does not check the types of data. At run time, the interpreter executes procedures that are appropriate for the type of the data, eg,

PYTHON

>>> a = '1'
>>> b = '2'
>>> a+b
'12'
>>> a=1
>>> b=2
>>> a+b
3
>>> 

This is called duck typing.

Before running Python code, one can use tools such as mypy to look for consistency in types. To support that, Python supports type hints. EG,

BASH

$ cat > foo.py
a : str = '1'
b : str = '2'
print(a*b)
$ python foo.py 
Traceback (most recent call last):
  File "/mnt/precious/home/andy_nix/projects/SIAMDS27/learner_setup/foo.py", line 3, in <module>
    print(a*b)
          ~^~
TypeError: can't multiply sequence by non-int of type 'str'
ds27$ mypy --strict foo.py
foo.py:3: error: Unsupported operand types for * ("str" and "str")  [operator]
Found 1 error in 1 file (checked 1 source file)
$ rm foo.py

Notice that mypy found the problem before running the code.

Callout

MYPY

Google AI says

Mypy is an optional static type checker for Python that analyzes your source code to detect bugs and type mismatches before your program ever runs. Because Python is traditionally a dynamically typed language, typos or invalid variable types normally crash your application at runtime. Mypy acts like a powerful linter, scanning your type annotations (type hints) to ensure type consistency across your codebase.

Here is the Makefile block that we will use to invoke mypy

## check-types         : Checks type hints
.PHONY : check-types
check-types:
	export MYPYPATH=$$PYTHONPATH; mypy --strict src/analysis

And here is what mypy has to say about our code

BASH

$ make check-types

OUTPUT

export MYPYPATH=$PYTHONPATH; mypy --strict src/analysis
src/analysis/testzipf.py:9: error: Missing type parameters for generic type "list"  [type-arg]
src/analysis/testzipf.py:30: error: Missing type parameters for generic type "list"  [type-arg]
src/analysis/testzipf.py:45: error: Function is missing a type annotation  [no-untyped-def]
src/analysis/testzipf.py:84: error: Call to untyped function "main" in typed context  [no-untyped-call]
src/analysis/countwords.py:10: error: Function is missing a type annotation  [no-untyped-def]
src/analysis/countwords.py:29: error: Need type annotation for "counts" (hint: "counts: dict[<type>, <type>] = ...")  [var-annotated]
src/analysis/countwords.py:65: error: Function is missing a type annotation  [no-untyped-def]
src/analysis/countwords.py:85: error: Call to untyped function "word_count" in typed context  [no-untyped-call]
src/analysis/countwords.py:91: error: Call to untyped function "main" in typed context  [no-untyped-call]
Found 9 errors in 2 files (checked 2 source files)
make: *** [Makefile:49: check-types] Error 1

Let’s address those issues now.

Key Points
  • We use yapf to coerce Python code into standard use of white space
  • We use lint to detect deviations of our Python code from standards specified in pylintrc
  • We use mypy to check our use of Python type hints