Since last year, I’ve been a teaching assistant in the Introduction to programming for physicists course at The University of Manchester. This is taught in the first semester of Y2 and we introduce them to Python. While marking the students’ assignments, we have noticed that most of the deductions were made in style. All these are common mistake, but when accumulated, they make the code hard to read. Here are a few notes on coding style. More can be find from PEP8 or Google Python Style Guide.
Structure your code
A good code structure would be the following:
- import statements
- constant definitions
- function definitions
- main code
It should contain a title (e.g. the name of the programme), an author and a date. This allows the reader to quickly understand the purpose of the code, without having to read all the lines in the file. Including the author name serves for copyright, but importantly, indicates who to contact for a question or any request about the code. The date serves to check whether the code is up-to-date.
# -*- coding: utf-8 -*- """ example_header.py The purpose of this code is to show an example of a header. Note the first line about encoding. It is good practice to keep it as it allows some IDE to enforce the encoding and prevent some bugs. This is mostly a Python 2 feature. Last updated: 31oct 2019 Julien Barrier - firstname.lastname@example.org """
They are useful because it allows us, in this course, to set values specific to the problem we want to solve. When evaluating, we — the examiner — may change these constants and check the program result. It is much easier to have them early than trawling through the code to update every occurrence.
In python, we define constant names with the following convention:
It is good practice to define a comment inside the function, to describe quickly what the function does and tell the variable type for the input and output arguments.
def joule_to_ev(value_joule): ''' Converts an energy value from Joule to eV args: value_joule (float) ''' value_ev = value_joule/1.60e-19 return value_ev
Name your functions/variables
All the names for functions/variables should be self explanatory. They should be written in full English. For example, it is always better to write
mass = 3.0 rather than
m = 3.0.
Ideally, you should look for self explanatory names, meaningful and concise.
maximum line length
It is common to have no longer than 79 characters on a line, so that all the code is visible without having to scroll horizontally, on any screen.
break a line within a function
The convention used when writing a function is to include an extra level of indentation for the variable names.
def function( variable1, variable2, variable_with_a_very_long_name, variable3, variable5): # default indentation level for the function
break a line in an expression
The convention is to break the line before the mathematical operator, and align it to the innermost parenthesis.
When you call a function, break the line at the coma, and the next line should start at the level of the opening parenthesis.
When breaking the line in a middle of mathematical operation, it should be done such as the next line starts with the operator at the same level as the previous term. Most of the time, the whole expression should be wrapped up within parenthesis (or eventually a backslash
\ ), to ensure Python understands.
The amount of blank lines should be adjusted carefully. If there are too much, the code looks sparse and is hard to read. If there are too few and you have only one block of code, it becomes hard to analyse. Function definitions should be surrounded by two blank lines above and below. Otherwise, use blank lines to show the structure of the code and separate different logics.
Whitespaces should be included as in standard typography rules. That means they should not be included:
- before a coma, semicolon or colon;
- before or after a parenthesis, bracket or brace;
- before the open parenthesis/bracket starting a function, an argument list a list indexing or slicing.
- when passing a kwarg (keyword argument, e.g.
plt.plot(x, y, ls='-', lw=.5, c='r'));
- at the end of a line;
- to align tokens on consecutive lines, such as
On the other hand, they should be included:
- around assignment operations (
- around comparisons operators (
- around Booleans (
- after a hashmark in a comment (
- when a mathematical operation contains different levels of priority, include whitespaces to show priority (e.g.
y = x*2 - 1)
This code calculates a value of π using a Monte Carlo method: This code is not the most efficient but shows the general structure we expect in the Introduction to programming for physicists course.
# -*- coding: utf-8 -*- """ Monte Carlo pi Program that calculates a value for pi using a Monte Carlo method Last updated: 31oct 2019 Julien Barrier - email@example.com """ import random import math import matplotlib.pyplot as plt ITERATIONS = 1000 def check_unit_norm(x,y): """ Checks if inputs are inside the unit circle x (float) y (float) returns Boolean """ if math.sqrt(x**2 + y**2) <= 1: return True counter = 0 for i in range(1,ITERATIONS): # we pick a random X,Y position X = random.random() Y = random.random() if check_unit_norm(X, Y): COUNTER += 1; plt.plot(X, Y, 'bo') else: plt.plot(X, Y, 'ro') # we print out the current value of pi after every 100th point if i > 0 and i % 100 == 0: print ("Currently %9.7f\n" % (4 * counter / i)) pi = 4 * counter / ITERATIONS print("A value for pi is %9.7f\n" % pi)