PEP8_python_code_structure_template - neuralinterfacinglab/LabManual GitHub Wiki


''' 
This pseudocode highlights the basics of creating readable code, please 
also read the PEP8 guidelines. 

Always program with the following in mind:
	- I need to understand the code quickly when I have not seen it for 6 months.
	- My colleagues must be able to read my code when collaborating.

When in doubt, add comments!

-----------

Always use the following order of sections:

IMPORTS
	builtint libraries
	3th party libraries
	local libraries
CONSTANTS
CLASSES
FUNCTIONS
OTHER CODE

'''

## IMPORTS

# Start with builtin python libraries
import sys # All libraries go on a single single
import os
from pathlib import Path
from math import sqrt, sin # You can import submodules on the same line
from math import *  # There is never a good reason to import all, so prevent using this.

# After builtins come 3th party libraries (the ones you install with pip)
import numpy as np
import matplotlib.pyplot as plt

# Finally, import the local libraries, i.e. libraries you've written yourself
from some_second_file import your_own_function

## CONSTANTS
'''
Constants are used for variables that do NOT change.
Constants are always uppercase
Contants should be defined before your function definitions, and can be 
used within functions.
Contants can greatly increase the readability of your code. For example,
the contacts LINE_NOISE_FS is immediatly clear, while the number 50 needs
some extra thought.
''' 

LINE_NOISE_FS = 50
FIGURE_SIZE = (16, 8)

MY_PATH = Path('path_to_data')  # pathlib is the successor of os.path. Very readable 
								# and useful. 

## CLASSES

class YourClass(inheritedParentClass):  # Classes are defined in CamelCase, 
										# all other variable use underscores
	def __init__(self):
		pass
	# One line between methods (remember that a function within a class is called a method)
	def some_method(self):
		pass
					# two lines
					# between and after classes
class YourSecondClass(inheritedParentClass):

	class_constant = 1 # Class constants go here

	def __init__(self):
		pass


def your_function(input_one, input_two=some_value):  # Use spaces between variables! Make it
													 # as readable as possible
	# See how I immidiately know why this line is here by using a well named constant?
	filtered_data = some_notch_filter(input_one, frequency_to_remove=LINE_NOISE_FS)  

def your_next_function(var_1,
					   keyword_arg_1=1,
					   keyword_arg_2=2):
	# If you have many function arguments,
	# considered lining them up
	return some_value

def main():
	'''
	You can highlight the entry point of your script with main.
	Use this function to create a high level overview of what
	your script is doing.

	Script too long? Move groups of functions to other files
	and import them! Make sure to name these files with 
	informative names as well, try to prevent names as: libs or 
	utils.
	'''

	# Example of using informative name functions, See how the general 
	# structure of this code is immediately clear?
	seeg = load_path(MY_PATH)
	seeg = clean_data(seeg)
	power_bands = apply_filter_hilbert(seeg)
	model, score = train_model(power_bands)
					# Two lines
					# after sections with functions
if __name__ == '__main__':
	'''using __name__ == '__main__' is good practice,
	   When you import a function, the whole script is run.
	   Without __name__=='__main__', the function calls at 
	   the bottom will also be run. This is usually not
	   what you want. Wrapping those function calls
	   in __name__=='__main__' will prevent that from 
	   happening, and allows you to import the file in
	   other functions'''
	main()