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
andylim
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 lucky2.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!