This notebook contains an excerpt from the Python Programming and Numerical Methods - A Guide for Engineers and Scientists, the content is also available at Berkeley Python Numerical Methods.

The copyright of the book belongs to Elsevier. We also have this interactive book online for a better learning experience. The code is released under the MIT license. If you find this content useful, please consider supporting the work on Elsevier or Amazon!

# Avoid Errors¶

There are many techniques that can help prevent errors and make it easier for you to find them when they occur. Because becoming familiar with the types of mistakes common in programming is a “learning as you go” process; we can not possibly list them all here. That said, we present a few of them in the following section to help you build good habits.

When writing an essay, it is important to have a structure and a direction that you intend to follow. To help make your structure more tangible, writing an essay usually starts with an outline containing the main points you wish to address in your paper. This is even more important to do when programming, because computers do not interpret what you write. When coding complicated programs, you should start with an outline of your program that addresses all the tasks you want your program to perform and in the order in which it should perform them.

Many novice programmers, eager to finish their assignments, will rush to the programming part without properly planning out the tasks needed to accomplish the given task. Haphazard planning results in equally haphazard code that is full of errors. Time spent planning out what you are trying to do is time well spent. Pre-planning will ensure that you will finish your program much faster than if you throw together a program without much thought.

So what does planning a program consist of? Recall in Chapter 3 that a function is defined as a sequence of instructions designed to perform a certain task. module is a function or group of functions that perform a certain task. It is important to design your program in terms of modules, especially for tasks that need to be repeated over and over again. Each module should accomplish a small, well-defined task and know as little information about other functions as possible (i.e., have a very limited set of inputs and outputs).

A good rule of thumb is to plan from the top to bottom, and then program from the bottom to the top. That is: decide what the overall program is supposed to do, determine what code is necessary to complete the main tasks, and then break the main tasks into components until the module is small enough that you are confident you can write it without errors.

## Test everything often¶

When coding in modules, you should test each module using test cases for which you know the answer, and code enough cases to be confident that the function is working properly (including corner cases). For example, if you are writing a function that tells you whether a number is prime or not, you should test the function for inputs of 0 (corner case), 1 (corner case), 2 (simple yes), 4 (simple no), and 97 (complicated no). If all of your test cases proceed without error, you can move on to other modules, confident that the current module works correctly. This is especially important if subsequent modules depend on or call the module you are working on. If you do not test your code and assume that your incorrect code is correct, when you begin to get error messages in later modules, you will not know whether the error is in the module you are working on or in a previous module; this will make finding the error exponentially more difficult.

You should test often, even within a single module or function. When you are working on a particular module that has several steps, you should perform intermediate tests to make sure it is correct up to that point. Then, if you ever get an error, it will probably be in the part of your code written since the last time you did test it. This tendency to rush one’s coding is a mistake even seasoned programmers are guilty of; they will write pages and pages of code without testing and then will spend hours trying to find a small error somewhere.

Just like good craftsmen keep their work area as clean as possible, free of unnecessary clutter, so should you keep your code as clean as possible. There are many strategies you can implement to keep your code clean. First, you should write your code in the fewest instructions possible. For example,

y = x**2 + 2*x+1


is better than

y=x**2
y=y+2*x
y=y+1


Even if the outcome is the same, every character you type is a chance that you will make a mistake; therefore, reducing how much code you write will reduce your risk of introducing errors. Additionally, writing a complete expression will help you and other people understand what you are doing. In the previous example, in the first case it is clear that you are computing the value of a quadratic at x, while in the second case it is not clear. You can also keep your code “clean” by using variables rather than values.

EXAMPLE: Poor implementation of adding 10 random numbers.

import numpy as np

s = 0
a = np.random.rand(10)
for i in range(10):
s = s + a[i]


EXAMPLE: Good implementation of adding 10 random numbers.

n = 10
s = 0
a = np.random.rand(n)

for i in range(n):
s = s + a[i]


The second implementation is better for two reasons: first, it is easier for anyone reading your code that n represents the number of random numbers you want to add up, and it appears rationally where it is supposed to in the code (i.e., when creating the array of random numbers and when indexing the array in the for-loop); and second, if you ever wanted to change the number of random numbers you wish to add up, you would only have to change it in one place at the beginning. This reduces the chances of making mistakes while writing the code and when changing the value of n.

Again, this is not critical for such a small piece of code, but it will become very important when your code becomes more complicated and values must be reused many times.

EXAMPLE: An even better implementation of adding 10 random numbers.

s = sum(np.random.rand(10))


When you become more familiar with Python, you will want to use as fewer lines as possible to do the same job; therefore, a familiarity of the common functions and how to use them will make your code more concise and efficient.

You can also keep your code clean by assigning your variables short, descriptive names. For example, as noted earlier, n is a sufficient variable for such a simple task. The variable name x is probably a good name since x usually holds value of position rather than a number; but theNumberOfRandomNumbersToBeAdded is a poor variable name even though it is descriptive.

Finally, you can keep your code clean by commenting frequently. Although no commenting is certainly bad practice, over-commenting can be equally bad practice. Different programmers will disagree on exactly how much commenting is appropriate. It will be up to you to decide what level of commenting is appropriate.