Bugs hall of fame

Read the error!

This is the starting point. Even if the error message can appear cryptic, this is the reason the code is not working and it is half of the information you have.

The other half is the line where the error appears.

Infinite loops

infinite loops are hard to debug as the program/cell is still running and either

  • no output is generated
  • too much output is generated

It is good practice to introduce a cutoff in infinite loops

icounter = 0
while True and icounter < 10000:
    icounter += 1
    # do something
    if condition :
        break

if icounter == 10000:
    print ("I got enough of this loop!")

Off-by-one errors

This is an error where a loop executes one too little or once too much.

The following code executes nsteps times

for i in range(nsteps):
    result[i] = ...

with the largest value reached is i = nsteps - 1.

range(beg, end) loops over all values between beg and end-1, in total end-beg values.

It is often easier to reason about the first element and the number of steps required rather than the index of the last iteration.

xxx object is not subscriptable

This error comes when we use the array access syntax x[i] for some varialbe x that is not an array or not subscriptable.

def f():
    return [1,2,3,4]

f[1]
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-4-3e4b5c2a1894> in <module>()
      2     return [1,2,3,4]
      3 
----> 4 f[1]


TypeError: 'function' object is not subscriptable

Here f is the function, it need to be called to return an array:

f()[1]
2

list indices must be integers or slices, not XXX

This happens when the index in an array subscript is not an integer:

xs = [0.1,0.5,0.9]

for x in xs:
    print(xs[x])
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-2-27f905c987d0> in <module>
      2 
      3 for x in xs:
----> 4     print(xs[x])


TypeError: list indices must be integers or slices, not float

This often happens when you want to to iterate through an array and use the array as the loop counter instead of using a range.

If you want both the value in the array and its index, use enumerate:

for i, x in enumerate(xs):
    print("{} is at position {}".format(x,i))
0.1 is at position 0
0.5 is at position 1
0.9 is at position 2

TypeError: ‘XXX’ object is not callable

With xxx either float or int. This happens normally when parenthesis are forgotten.

3(x-y)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-23-112ceb8d6610> in <module>()
----> 1 3(x-y)


TypeError: 'int' object is not callable

Looping over multiple loops

Often we want to loop over two list and combine the elements at the same position:

xs = [1,2,3]
ys = [4,5,6]

for i in range(len(x)):
    print ("x is", xs[i], "and y is", ys[i])
x is 1 and y is 4
x is 2 and y is 5
x is 3 and y is 6

We can use the builtin function zip

for x,y in zip(xs, ys):
    print ("x is", x, "and y is", y)
x is 1 and y is 4
x is 2 and y is 5
x is 3 and y is 6

It makes the code more readable!

My plot is not displayed!

In most cases you are asking to plot something that

  • cannot be plotted
    • nan
    • negative values on a log scale
  • is plotted but is out of the limits you set with xlim and ylim
import matplotlib.pyplot as plt
%matplotlib inline
data = [10,3,-1,-2,5]
plt.yscale('log')
plt.plot(data);
data = [1,2,3,4,5]
plt.ylim((0,1))
plt.plot(data);

My code is weird

  • it does not work the first time round, but it works the second time
  • it worked for my friend, but not for me

In most cases this is due to using uninitialised memory.

numpy.empty reserves the memory for an array, but does not set the values to anything in particular, it is whatever used to be there, so it can be

  • 0: you got lucky!
  • 1.3e-301: you are probably lucky
  • 2.334e+78: at least you will get a result…
  • nan: everything will break
  • anything else

If you encounter random behaviour (and you did not program it) look for numpy.empty arrays you did not fill completely.

  • replace with numpy.zeros
  • replace with numpy.full( (...) , 987654321 ): if you see 987654321 anywhere, this is a value you shuld have overwritten!