The title of this video is debugging lesson. In this video, we're going to go a little bit deeper into debugging, build on some of the concepts that were introduced in the debugging light video in lesson 2. We're going to start out by talking about a few of the guidelines to debugging. Something to keep in mind is that debugging is always part of programming. It's always something that you're going to have to do. You'll get better at it and as you get better at programming, you'll make less mistakes. But it's really always something that's going to remain part of programming. Something to keep in mind is that Python is a logical tool, so it's not breaking because it doesn't like you, it's breaking because of a specific reason and debugging is really hunting down, finding out that reason. That might also mean writing your program in a very different way than you're trying to write it, so looking for workarounds to the problems that you might be having. Another thing, too, to remember is to work methodically and that means that as you work on your programs, get one part to work before you move on to the next or move on to the next, because if something doesn't work, if you add more stuff to it, that's not going to make it work any better. When we get into talking about functions and using them more, we'll see that we'll be able to break the program into specific parts and work on them separately, which actually helps with the process of debugging. Last thing to remember is that speculation is different than guessing. A part of debugging is speculating about what might be wrong with your code and these are educated speculations. They're not guessing. Guessing doesn't really ever work with coding because it is a logical structure. You can't just write anything you want. So it's important to remember, again, to work on things in a very careful and logical manner. Now, we don't have time in this lesson to go through every single error that you may encounter in your process of coding, that there's a lot of different things that might cause errors. So instead of doing that, I'd like to talk about the three fundamental error types that you're going to be facing. By the end of this course, you should be able to at least identify those three types and that's going to help you hunt down what the problems might be. So these are syntax errors, logical errors, and semantic errors. Now, syntax errors, we talked about in debugging light and they're really the most common types of errors that not only beginners make, but advanced coders make too. They're typically errors in typing in the code, typing something in incorrectly. That could be the function, and it could be in the name of a variable. It could be your use of parentheses, a number of arguments that you put in might be wrong. So all those things are syntax errors. So in this example, which is one we looked at in debugging light or one version of it, so in my assignment, I'm writing int capital X and then when I call it in line 2 or use the variable in line 2, I write it incorrectly. I don't write the capital X. Something to point out here, too, in the message, it's not telling me specifically that I have a syntax error. Sometimes it'll say that it is a syntax error, but it's saying that this name is not defined. It means Python saying, it doesn't know what you're talking about because it doesn't know what this variable is. Now, this can happen if I write a variable incorrectly later in the code. It could also happen if I just use a variable that I have yet to assign, so I would get the same type of error. Again, our traceback usually gives us a line or two that points out where the error might be. But something to remember is that the error might not always be in that line that it's pointing out, like with our next example. So another very common syntax error to make is to forget to put a parentheses, not only on the end, although that's a typical way to do it, but we might also forget a parentheses in the middle of something. We'll find, as our code gets more complicated, using things like dictionaries, we have a lot of different parentheses in a line of code, and it's easy to forget one. So that's a very common error and it'll throw some type. It's not always going to look like this, but it might look something like this. It's saying there's an unexpected token print. The strange thing is that it's throwing the error from line 2, even though I forgot the parentheses in line 1. The reason it does that is that because I'm forgetting this ending parentheses. It sees line 2 as part of line 1 so it's throwing the error down here. It's saying, print doesn't make sense as part of the AddLine function because it doesn't understand that. It's an unexpected thing, unexpected token. In this example, I'm selecting some points within the scene and I'm filtering that, my selection, but I'm getting an error. It doesn't seem to be working and it's telling me something called a class object has no attribute points. When we get this error that says something has no attribute, it means typically, that's for a method for a function or it could be an additional argument that we're giving to something. It doesn't understand it as part of its language. So the problem here is that I'm using RS filter, so that's this class object that it's referring to. I believe I've written it in the correct format, which I have. I've put a period followed by points. But the problem is there's no points, it's only point. I use the filter point for whether I'm selecting one point or multiple points. So it doesn't know what points is, and so that's another type of syntax error that we can make, is to ask for something incorrectly in a function. Now, logic errors occur when everything is fine within the syntax, but I might be either giving something or requesting something that's incorrect. A very common logic error can occur within iteration and we'll particularly run into that when we're writing these exponential sections of the code where I might be asking for an i value that's either a plus one or a minus one in a loop. What happens is this is throwing an error which is an index out of range error and it's giving me a value. It's saying, "Hey, the number 3 is out of range." Well, what happens in the loop? We know that this is our 0 index, this is our 1, and this is our 2 and I'm giving an i plus 1. So actually, the first time through here it'll select peach and then the second time through, it would print out pear. It doesn't actually do any of that because it throws the error before it prints anything out. But that occurs when I get to the last time through the loop, i is 2, and I'm adding one to that, and I'm asking for three. So I'm asking for something that doesn't exist. I'm asking for a part of the index that it's saying is out of the range. So a couple of ways to remedy this. I could put in a conditional statement before my print that says, "Hey, don't go beyond three. Don't select if your index is greater than two. Don't do this." The other way to do it, and actually, a very common way to do it is, right in here, subtract one from the length of the list, and then it's going to give me one less, which it will allow me, then I can select one more here and it wouldn't break. So that's a logic error. Another type of logic error is to give something that you think is correct and it's actually not. You're giving an incorrect piece of data, you think it's in the correct form. So in this case, AddLine, I could AddLine would accept an ID. This is going to either accept a set of coordinates or it's going to select an ID or take an ID. I've given it an ID because I'm using the GetObject, which returns an ID to the variable point. But the error that it's throwing is saying it could not convert and it would convert, it would extract from that ID, which it's showing me here, we can identify that as an ID, to a 3D point, and it's saying, it can't do that. So something must be wrong with the type of ID that I'm giving it. What I've done is I've made an error up here. Instead of filtering points, I've filtered a curve and so if I'm group-selecting a bunch of things and I think I'm just going to get the point out of that, what it's actually selected is the ID of a curve, and so it's identified it as a curve, and it can't convert a curve into a 3D point. So that's another logic error, is I'm giving the incorrect type of data, or actually it's the correct type of data, but it's in an incorrect form because it's a curve. Now, the last and probably the most difficult to identify are semantic errors and that's because it doesn't really show up as an error in your output. You won't get any error message. Everything seems to run fine. It's just that your code is not outputting what you thought it would output. You're not getting what you thought you would. In semantic errors, your syntax is fine, your logic is fine, but there's something wrong with the code. In this example, this is a little snippet of code from a code we're working with in previous lesson under conditionals, and we were randomizing the radius of a circle, and then we would select the radius to keep it below a certain number, and then keep it above a certain number, and we're trying to establish a range of that radius. In this example, I'm showing a fairly large radius of 10, and I'm not getting that large radius when I run this code. The problem is that my multiplier that I've assigned up here with my random function is too small, so it's too small to produce large enough circles that they would need to be limited by this first conditional. I'm not really getting what I thought I would in the range of circles, and so this is my semantic error. This number would have to be something larger, let's say at least 10, maybe 15, to get the larger size circles that I want. That's a semantic error. Semantic errors are probably the trickiest to hunt down, again because I'm not getting any information about a line that's wrong within the code. Now from the chapter that I asked you to take a look at in Charles Severance's book, Python for Everyone, I think there's an excellent section that I'm calling the four Rs. I don't think he called it the four Rs in his book, but the four Rs in order to remember them, I think is useful. That's the reading, running, ruminating, and retreating when you're debugging. First is reading. Reading is just carefully reading your code, and this typically you're doing this if you have a syntax error, you're trying to look for those variables that you might have written wrong or that parentheses that you might have forgotten, or the function name that you might have written incorrectly. Particularly important for you, this issue of legibility within the code, this is one of the reasons why we follow those rules for writing the variable names is so I can easily read them within the code, and also why you might want to spend some time commenting your code very carefully so you can figure out the parts of it. First is reading, next is running. You might need to run different versions of your code, do save as versions of your code and start in a methodical way, changing things within those copies of the code and running them to try to figure out what's going wrong in the code. Third is ruminating. That's just essentially taking some time to think what could be wrong with your code, what type of error is it? Is it a syntax error? Is a logic error? Is it a semantic error? Trying to think about when did the error occur is very important. At what point when you're working on your code did you throw that error? That's why it's also very important to write your code a little bit at a time and to run it, and make sure it's running before you go to the next part. Because if it's not running at one part, if I add more, it's not going to make it run any better. The last is retreating. You've probably noticed in a lot of the tutorials, I used the comment, I comment out sections of the code to what I call turning them off. That could be a form of debugging, could be a form of retreating to where you turn off sections of your code in order to go back to that point at which the code was running without an error, and then rebuild your code from there. It's not necessarily, you don't want to go in and necessarily delete sections of code, you don't need to do that, you can use the comment to turn them off, retreat to a point where it's working, and then go from there. That is debugging, again it's something that's not going to go away, it's something that is just part of the culture of coding, something you have to get used to. Sometimes it can actually be fun finding that little, it's almost like a treasure hunt when you find that little problem and correct it.