Free YouTube Transcribe

Video transcript

CS50P - Lecture 3 - Exceptions

CS50 · 8,689 words · 40 min read

Want to search this transcript, jump the video from any line, or download it as TXT, SRT, or VTT?

Open in the transcript tool

Full transcript

Introduction

0:00[MUSIC PLAYING]

Exceptions

0:24DAVID MALAN: All right, this is CS50's introduction

0:27to programming with Python.

0:28My name is David Malan.

0:29And this is our week on exceptions.

0:31Exceptions in Python as well as in other programming languages

0:35refer to problems in your code.

0:37Indeed, when something is exceptional in your program,

0:40it actually doesn't mean it's a good thing.

0:41It means something has gone wrong that, ideally, you will somehow solve.

0:45So what are some of the things that can go wrong?

0:47So I'm going to go ahead and open up VS Code on my computer here.

0:50And in the terminal window, I'm going to go ahead and run code of hello.py.

SyntaxError

0:54That's going to, of course, open up a brand

0:56new tab for me, hello.py, in which I can write my code.

0:59And let me go ahead and write some very simple code just

1:01to say hello to the world.

1:03Let's go ahead and say print "hello, world.

1:08And then let me go ahead and--

1:10I'm forgetting to close that quote.

1:12So a mistake that you yourself might have already made

1:14or might surely in the future make-- and it's a little subtle

1:17because you might not necessarily notice that you've just

1:19missed that one character.

1:20Well, let me go ahead and somewhat optimistically

1:23go down to my terminal window now and run Python of hello.py and hit Enter.

1:28And that's the first of my errors.

1:29My gosh, I've only written one line of code.

1:31And I seem to have more lines of errors on the screen.

1:34But the salient point is this bottom-most thing here.

1:37Notice where it says syntax error.

1:39A syntax error is a problem with the code that you have typed, your syntax.

1:43Just like English and other human languages

1:45have syntax associated with them, so does my code.

1:47And it's not quite correct.

1:49Something is awry.

1:50I didn't follow the instructions properly.

1:52And it does elaborate for me, unterminated string literal.

1:56Now, that's a bit arcane.

1:57That is a bit of a confusing error message.

1:59But unterminated would generally mean that I

2:01started something but didn't stop it.

2:03I didn't terminate it.

2:05String, of course, is a sequence of text, like we've discussed before--

2:08or stir in Python.

2:09And literal generally refers to something that you literally typed.

2:13It's not a variable.

2:14It's something like quote unquote--

2:15or just "hello world.

2:18So the fix here, of course, is going to be

2:20to go ahead and terminate that string and actually close the quote.

2:24And if I now go back down into my terminal window

2:27and rerun Python of hello.py, now I'm saying hello to the world.

2:31So the catch with syntax errors here is that syntax errors are entirely

2:36on you to solve.

2:37A syntax error is a problem that you've got to go back into your code

2:40and fix from the get-go.

2:41You can't just kind of hope that it's going

2:43to resolve itself or expect that other parts of your code

2:47will catch it for you.

2:48Syntax errors just must be fixed.

2:50But there's a lot of other types of errors in Python

2:53that might be described as runtime errors, that

2:55happen while your code is running.

2:57And it's really up to you to write some additional code defensively

3:01to detect when those errors happen because you don't necessarily know,

3:05for instance, what input humans are going to type into your program.

3:08And so you better be ready, defensively, to accommodate things

3:11that they type or even misstype.

3:13So, for instance, let's go back over here to VS Code.

3:17And let me propose that we take a look at a new file all together.

3:20I'm going to close hello.py.

3:22And I'm going to write code of say number.py.

3:26So let's play around with some numbers in Python.

3:28And the first thing I'm going to go ahead here and do with number.py,

ValueError

3:32after opening this new tab, is I think I'm going to go ahead and print--

3:35type up a relatively simple program that maybe prompts the user for an integer,

3:40like x, and then just prints out what x is.

3:43So we're going to start simple, but, again, in starting simple,

3:45we'll be able to really see where I've done something wrong.

3:48Well, here we go.

3:49I'm going to go ahead and say a variable called

3:51x is going to get assigned the value of the return value of input,

3:57quote unquote, "what's x?"

3:59And I'm going to include a space to move the cursor over a little bit.

4:02And then, ultimately, I'm going to go ahead and-- oh, wait a minute.

4:05If I'm wanting to get an int from the user,

4:08recall that I need to do something proactively.

4:10I need to actually convert that input to an integer using

4:14the int function in Python.

4:16So now I'm passing the return value of input as the argument to int.

4:20And that will store in x, ultimately, an integer, not

4:22a string that looks like an integer.

4:24All right, let me go ahead now and just quite simply print out what this is.

4:28I'm going to go ahead and print out, quote unquote, "x is x."

4:32But I don't want to literally say x is x.

4:34I want to plug in the value of x.

4:36So maybe the easiest way to do that is to surround it with curly braces.

4:40And then if I'm using these curly braces and I

4:42want Python to interpolate the value of that variable,

4:45that is substitute what x actually is in between those curly braces,

4:49recall that I need to use a format string or an F-string

4:52by fixing this whole thing with an F. Now that I've done that, let's go ahead

4:56and see what happens.

4:57I'm going to go ahead in my terminal window and run Python of number.py.

5:02I hit Enter.

5:02And so far, so good.

5:03All is well and being prompted for x.

5:05Let me go ahead and type in a number like 50.

5:08All right, that seems to work.

5:09Program seems to be correct.

5:12Or is it?

5:14What could go wrong in this program, even though nothing did just go wrong?

5:19But if I run it and run it and run it again,

5:22during the running of my program, what could still go wrong,

5:26especially if I'm not the human interacting with it

5:28but some other human instead?

5:30Any volunteers here for this one?

5:33What could go wrong?

5:35And in what way is this program not really correct, even

5:40though at first glance it seems so.

5:42AUDIENCE: [INAUDIBLE]

5:52DAVID MALAN: So I'm not calling an integer.

5:54I'm still having trouble hearing you.

5:56But what I think I heard is that if what the user types in is not,

5:59in fact, an integer, I can't just blindly convert it to an int.

6:03If I'm not putting too many words into your mouth,

6:05I think what I should perhaps do here is be a little defensive.

6:10And let me see if I can't simulate exactly the problem that

6:14could go wrong here.

6:14Let me go ahead and run, again, Python of number.py.

6:18Let me try another number.

6:19In fact, when testing your code, generally it's

6:21a good idea to test corner cases, maybe numbers that aren't quite as plain as

6:25or 49 or 51.

6:27Let's choose some numbers that might be a little more interesting, if only

6:30mathematically, like zero.

6:32All right, zero seems to work.

6:34My code still prints out that x is zero.

6:35What might be another corner case to consider?

6:37Well, let me go ahead and try a negative number.

6:39That, too, is pretty different in spirit from negative.

6:42Negative 1?

6:43OK, that works too.

6:44Well, let me try it one more time.

6:46I've tried positive numbers, negative numbers, 0.

6:48Let me try something like a cat.

6:50So literally, C-A-T-- typing in a string that doesn't even look like a number.

6:56And yet, let's see now what happens when I hit Enter.

6:58All right, we'll see now we've got another kind of error.

7:01It's not a syntax error, because I didn't make a typographical mistake.

7:05I didn't forget some piece of syntax.

7:07I actually now have an error with one of my values.

7:10And it's an a value I didn't even anticipate.

7:12The human, me, in this case typed it in long after I wrote the code.

7:17So what does this refer to?

7:18A value error.

7:19Well, let's see what the explanation is.

7:21Invalid literal for int with base 10, quote unquote, "cat."

7:25Now, this, too, is a bit of a mouthful.

7:27And, unfortunately, in Python and a lot of programming languages,

7:29the error messages are written for pretty comfortable programmers.

7:32And, of course, when you're learning programming for the first time,

7:35you might not be so comfortable with the programming language

7:38let alone the error messages.

7:40But let's see if we can't glean some insight.

7:42So invalid literal.

7:43Well, again, a literal is just something that's been typed in, it would seem,

7:47for int.

7:48What is int exactly?

7:50Well, int is the function I'm using to convert the user's

7:52input to a corresponding integer.

7:55Base 10, that refers to the decimal system, which is this

7:58the default that Python is using.

7:59And it looks like at the end of the day, what Python really

8:02doesn't like is that I passed cat, quote unquote, "to the int function."

8:07So how do I go about actually fixing this problem?

8:10Well, I could just add instructions in my program.

8:13Maybe I could add a line of print telling

8:15the user more explicitly, be sure to type an integer,

8:18or, please don't type cat.

8:20Please don't type strings.

8:21Of course, the user might still not oblige.

8:23They might not be reading the instruction.

8:25So that too is probably not an effective strategy.

8:27What we really want to do is write our code with error handling in mind.

8:31We want to write lines of code that not only accomplish

8:33the problems we care about but that also handle

8:36errors that might unexpectedly happen.

8:39And, in general, when programming, programming defensively.

8:41Assume that the users aren't going to be paying attention or, worse,

8:44they're malicious.

8:45They're trying to crash your program.

8:47So we want to handle as many errors as we can.

8:50Now, how do we go about doing that in Python?

try, except

8:52Well, it turns out whether you want to catch a value error or other types

8:56of errors as well-- though not syntax error--

8:59Python actually has this keyword called try.

9:01And it's sort of aptly named.

9:02If you want to try to do something in Python,

9:05you can literally use this keyword.

9:07And you can check whether or not something exceptional, something

9:11erroneous, has happened.

9:12So using both try and this other keyword, except,

9:16can I go and try to do something except if something goes wrong?

9:20I can do something else instead.

9:22So let's consider, how can I go about trying

9:25to convert the user's input to an int except if something goes wrong?

9:29Well, let me go back to my code here.

9:31And let me propose that I now modify this example as follows.

9:34Let me go ahead and, above my first line of code,

9:37I literally write, try and a colon, telling Python,

9:40try to do the following.

9:42I'm going to go ahead and indent my existing lines of codes

9:44here by the same number of spaces, four in this case.

9:47And then I'm going to add one more new line down here that literally says,

9:51except Value Error.

9:53And notice it's important that I've capitalized the V

9:55and I've capitalized the E. These symbols are case sensitive.

9:59And this is now an opportunity, after this colon,

10:02to tell Python what I want to do in exceptional cases, when

10:07the number or the input from the user is not, in fact, a number.

10:10And I'm going to say something plain like print, quote unquote,

10:13"x is not an integer."

10:15I'm at least going to tell the user roughly what the problem actually is.

10:19So notice another detail.

10:21The indentation is important.

10:22Because I have try on line one and I've indented lines two and three, those

10:26are the two lines of code that I'm trying, except if I see a value error,

10:30line five, because it's indented is what is

10:33going to get executed in cases of those errors.

10:36Let me go ahead now back to my terminal window and run Python of number.py,

10:43Enter.

10:44And let's go ahead and type in again.

10:47Still seems to work.

10:48And, of course, I'm trying and succeeding.

10:50Let me go ahead and try once more, this time, though, with the word cat

10:53or, really, anything that's not a decimal number.

10:55And now you'll see much more cleanly x is not an integer.

10:59I'm not seeing some scary error message that I, the user,

11:02am going to have no idea how to handle.

11:04Now you, the programmer, have anticipated

11:06that something exceptional can happen.

11:08And you've gone about actually handling the error for the user,

11:12giving them an appropriate error message instead.

11:15Let me pause here and see, are there any questions now

11:18on what we've just done by introducing try

11:21and accept to handle this value error?

11:25AUDIENCE: Is value ever the only type of error you can get?

11:28Or are there other types?

11:29DAVID MALAN: Is value error the only thing you can catch?

11:31There are other errors as well.

11:32And we'll see a few of them today.

11:33And there's many, many more, honestly, that if you continue

11:36programming and programming in Python, you're

11:38going to see a lot of them over the weeks the months the years to come.

11:41But the technique for handling them is going

11:43to be largely the same other questions on try, accept,

11:47or these exceptions more generally?

11:49AUDIENCE: Yes, sir.

11:51Actually, to use the except block, you need to know the type of error, right?

11:55[INAUDIBLE] what if you can't anticipate this particular type of error?

12:01DAVID MALAN: A really good question.

12:02So I'm being very good about catching, so to speak,

12:06the very error that I might happen.

12:08I don't know when it might happen because it's

12:10going to depend on the user.

12:11But I know what kind of error will happen from the int function.

12:15There is a way in Python where you can say, except if anything goes wrong.

12:19And you can literally omit value error and just catch everything.

12:23The problem with that is that it sometimes hides other bugs in your code

12:27because you don't necessarily know what's going wrong.

12:29And if you don't necessarily know what's going wrong,

12:32how can you possibly handle it correctly?

12:34So bad practice.

12:35And it put another way, it's lazy to do that, to just say, catch everything

12:38and I'll deal with it here.

12:40So a much better practice would be to figure out what kind of errors

12:43could happen and include mention of them explicitly, as I have done.

12:48Now, with that said, if you read Python's official documentation,

12:51as you'll eventually invariably do, it is not

12:54great about telling you proactively what kinds of errors

12:58can be raised in this way.

13:00So it's a bit of contradictory advice.

13:03You should do it this way.

13:04But it's not always obvious what you should be checking for.

13:07But you get better at it with practice.

13:09And some of the times, the documentation does spell out what could go wrong.

13:12Let me turn our attention now back to this

13:14and point out that even though this is better code,

13:17it is more correct in the sense that I'm not just leaving it to the user

13:21to see some really ugly default Python error message that most people are

13:25going to have no idea what to do with, I'm

13:27at least handling it more elegantly.

13:29And I'm printing out x is not an integer.

13:31So it's at least more instructive.

13:33But this isn't necessarily the best way to implement this code.

13:36Why?

13:36Well, here, too, I'm actually still being a little lazy.

13:39So notice that I'm trying to do not one line of code but two lines of code.

13:44And this isn't a huge deal because we're only talking about two lines of code.

13:47But in the interest of preaching best practices,

13:51you should really only be trying to do the one or very few lines of code that

13:56can actually raise an exception that can actually fail in some way.

14:01I am pretty sure that calling print here is not going to raise a value error.

14:06Whether x is an int or a string or a float or anything else,

14:10the format string feature of Python is going to handle printing it just fine.

14:15So, really, what I'm going to do is this.

14:17I'm going to move this line three down to the bottom of my code.

NameError

14:21I no longer need to indent it.

14:22I'm just going to execute it at the bottom of my file here.

14:26Unfortunately, by doing this--

14:28I've done a good thing by now only trying to do the minimal amount of work

14:32necessary that might raise the exception of value error.

14:36But I fear I've introduced a new mistake.

14:38Well, let's see.

14:39What is now incorrect?

14:40Let me go ahead and again run Python of number.py, Enter.

14:44Let me go ahead and do it correctly with 50.

14:46And all seems to be well.

14:48But, again, let's try those corner cases--

14:50the zeros, the negative numbers, or, in this case, the cat.

14:52Let me go ahead and type in C-A-T again.

14:55Enter.

14:55Now I have a name error.

14:57So now it's yet another type of error in my code that I've introduced here.

15:01And what does this name error mean?

15:03Well, just as a value error refers to that-- the value of some variable,

15:07the value that someone has typed in is incorrect--

15:09name error tends to refer to your code, like you're doing something with

15:13the name of a variable that you shouldn't.

15:16And why might that be?

15:17Well, let me turn our attention back to the code

15:19here and consider, what is it complaining about?

15:22Well, the name errors what I see down here.

15:24And it's telling me, name, quote unquote, "x is not defined."

15:28And notice if I look further here, it is mentioning line six.

15:31So I know the problem is with my code on line six.

15:35And that worked a moment ago.

15:38And I'm defining x on line two.

15:42But let me ask the group here, why does x, in fact, exist online six?

15:48Why is it not defined, even though I'm pretty sure I

15:52was intending to define it on line two?

15:54AUDIENCE: Maybe the scope of the variable is between the [INAUDIBLE]..

16:00DAVID MALAN: So, good terminology.

16:02Scope refers to the portion of code in which a variable exists.

16:06That, too, though isn't quite right in Python.

16:08That would be true in C, C++, and Java, where indentation or curly braces tend

16:12to define the scope of a variable.

16:15But, again, here in general--

16:16and this worked a moment ago.

16:18X exists once it's defined on line two because, remember,

16:22I printed out x is 50 a little bit ago.

16:24Let's try one more hypothesis here.

16:27One more hand?

16:29Why is x somehow still not defined?

16:32AUDIENCE: Yeah, so is it because it's local variable,

16:36meaning that it doesn't define outside of the scope

16:39because what people have mentioned.

16:42It prompts the input in try, right?

16:45The outside of it is undefined.

16:46DAVID MALAN: So still good instincts.

16:48And good terminology, too.

16:49There's this notion of local variables, which tend to exist inside

16:52of functions, for instance, global variables,

16:55which tend to exist in entire files.

16:57In this case, too, though, that's not quite the case.

16:59What's happening here boils down to order of operations.

17:03Let me come back to the code here and recall that any time we've

17:06discussed the assignment operator, the single equal sign, that copies

17:09a value from the right to the left.

17:11But consider for a moment at what point something is going wrong.

17:14Well, the input function is probably working just fine

17:17because we've used that a lot now to get users' input.

17:20It always returns a string or a stir in Python.

17:24But what could be going wrong?

17:25Well, if I'm passing that string to the int function as its argument,

17:32it's probably the int's function that's erroring.

17:34And, indeed, if you think back earlier when we had the value error,

17:37it was, in fact, the int function that did not

17:39like, quote unquote, "cat" as input.

17:42So this is all to say that this portion of my code

17:45highlighted now to the right of the equal sign, that's

17:48the code that's creating a problem.

17:50That's the code that was creating a value error.

17:53And in this case, we're catching the value error.

17:57But because the value error is happening on the right of the equal sign,

18:01there's no value being copied to the left.

18:03The error is interrupting that whole process.

18:06So even though we see x equals dot dot dot on line two,

18:10the portion of that line to the left of the equal sign

18:13isn't getting evaluated, ultimately, because the value

18:16error is happening too soon.

18:18And so when we finally get down to line six,

18:20even though it looked like I was defining on line two--

18:23and I would have defined x on line two if all had gone well--

18:26we didn't get to the part where the value is copied from right to left

18:29because the value error happened first.

18:31So this code is just incorrect now.

18:34So how do I go about solving something like this?

else

18:37Well, it turns out that there's another feature of the try

18:41and accept syntax that Python supports, which is

18:43that it also supports the keyword else.

18:46Now, we've seen else before.

18:47If you think back to our discussion of conditionals, we saw if.

18:51We saw elif.

18:52We saw else, which was kind of this catchall, what

18:55you should do in the event that nothing else is relevant.

18:58That's kind of the same intuition here for the try-except feature of Python.

19:02What you can do is this.

19:04You can try to do the following, as I've done, except if this goes wrong.

19:09But if nothing goes wrong, else go ahead and do this.

19:13So this is one way I can solve this same problem now.

19:16No matter what now, Python is going to try to execute line two.

19:21If something goes wrong, it's going to execute lines three

19:24and four to handle that value error.

19:26However, if you try and this code succeeds,

19:30then there is no exception to handle.

19:32So you're then going to execute this line here.

19:35So it's a little confusing, perhaps, in that

19:37we're now using else both for conditionals-- if, elif, elif, elif,

19:41else.

19:42And we're also using else with these try-except blocks.

19:45But that's OK.

19:46That's part of the language.

19:47That's one of the features.

19:48So now if I rerun this code in my terminal window, Python of number.py--

19:54let's do something correct, like 50--

19:56I see that x is 50.

19:58So line one is executed.

20:00We're trying to do the following.

20:01Line two is executed because the conversion happened successfully

20:05and the number 50 gets copied from right to left.

20:07The exception does not happen.

20:10So we ignore lines three and four.

20:11We jump immediately to line five and six, which prints out the result.

20:16By contrast, though-- let's do this one last time.

20:18Python of number.py-- let's type in cat or, again, any other word and hit Enter

20:23now.

20:23We don't see what x is.

20:25Rather, we see, quote unquote, "x is not an integer,"

20:29which is what's being handled in my except clause.

20:33All right, let me pause here because that's a lot of new syntax,

20:35and see here if there's any questions on try, on except,

20:39on else, name error, or value error.

20:42AUDIENCE: Can you please repeat the try function?

20:45DAVID MALAN: Repeat the name error?

20:47What's the problem with the name error?

20:48AUDIENCE: Yes.

20:49Yes.

20:49DAVID MALAN: Yes.

20:50So let's just rewind a couple of lines here

20:52before I fix this problem by now getting rid of the else.

20:55A moment ago, we had code that looked like this, whereby

21:00I was getting a name error, Python of number.py, Enter,

21:03typing in cat, that looked like this, where name x is not defined.

21:07And the problem was on line six, according to this output in Python.

21:11Well, let's think about this now deductively.

21:13Let's try a different approach.

21:15On line six, I'm seeing an error that name x is not defined.

21:18OK, Python's already telling me x does not exist at that point.

21:22So how could that possibly be?

21:23Well, where should x be defined?

21:26Well, presumably, x is defined on line two, up here.

21:29So what could go wrong?

21:31Well, if the user has inputted something that doesn't look like a number,

21:35like the word cat, passing cat, the return value of input,

21:40as the argument to int to convert the word to an int makes no sense.

21:45You can't convert a cat, C-A-T, to an integer at all.

21:49So the int function is raising a value error at that point.

21:55And the error is being handled with this code here.

21:58But notice this line six is not indented.

22:02It's left aligned with the rest of my code, which means no matter what,

22:06line six is going to execute.

22:08It's going to execute whether I typed in 50 or I typed in cat.

22:12But if I typed in cat, again, x never gets a value.

22:15So it's not defined here on line six.

22:17So when I introduced, finally, the else statement, that

22:21makes sure that these things are mutually exclusive.

22:23I only execute the else if I tried and succeeded up above.

22:29Well, let me propose that we refine this just a little bit further as well

22:35and consider how we might improve this example a little bit more.

22:39It's a little unfriendly of me to be rejecting the user's input after they

Reprompting, break

22:45fail to provide an integer and just quitting the program, really, right?

22:49It'd be more user friendly if I just prompt

22:51or reprompt the user again and again.

22:54And in the chat, if you could, what's the feature of Python

22:58that you can use if you want to do something again and again

23:01and again until such time as the user cooperates and gives you

23:04what you're looking for, like a number?

23:07So yeah, loop, loop, loop.

23:09So a loop is something that happens again and again and again.

23:12And maybe we can use that same mechanism, a loop, in order

23:15to prompt the user for x.

23:17And if they don't give us a number, prompt them again.

23:19And if they don't, prompt them again and again and again.

23:22We don't need to just quit out of the program.

23:24So, quickly-- so let me propose this.

23:26Let me propose here that I improve this code by deliberately doing this.

23:30Let me induce a infinite loop at the very top of my code with while true.

23:36Recall that the wild keyword induces a loop, a cycle that behaves like this.

23:40And it asks a question, a Boolean expression

23:42that needs to evaluate either to true or false.

23:45Well, if I want this thing to loop forever,

23:47at least initially, we'll just say while true because true is true.

23:51So this has the effect of doing something

23:53no matter what forever unless we break out of it early.

23:56Now I'm going to go ahead and do this.

23:58I'm going to go ahead and move my try except code

24:02indented underneath this loop so that I'm trying to get an x.

24:06If I have a value error instead, I print out x is not an integer.

24:11But this time, what do I want to do if the user does

24:15try and succeed in giving me a number?

24:18Well, I can do this.

24:20I can just break out of my code here.

24:22And down here now, I can use that same line of code

24:25from before, an F-string that says x is, and then in curly braces, x again.

24:31So what's going on here?

24:32I think this code now, because I've added

24:35the loop, is going to have the effect of trying at least once, maybe

24:39a second time, maybe a third time maybe 500 times until the user finally gives

24:44me what I want, which is an integer.

24:46And once they do, once there's no value error happening,

24:50then I break out of the loop.

24:51And line nine executes as I would hope.

24:54So let me go ahead and try executing this version--

24:56Python of number.py, Enter.

24:58What's x?

24:59Let me go ahead and type in the easy thing first--

25:0250.

25:03X is 50.

25:03What just happened in terms of the control flow

25:06of this program, the flow of my logic?

25:08Well, I first found myself on line one inside of a loop.

25:11Hopefully, I'll get out of this loop.

25:13What did I then do?

25:14On lines two and three, I tried to get input from the user

25:18and convert it to an int.

25:19Well, I was a nice guy this time.

25:20And I typed in 50, which looks like and is a number.

25:23So the int function converted it just fine

25:25and stored it from right to left in x.

25:28Except value error?

25:29There is no value error because if I typed in a number,

25:31there's nothing exceptional happening.

25:33This is a boring, good execution of my program.

25:36So what happens?

25:38I break out of the loop.

25:39So, again, the else clause is associated with the try not with the except.

25:44And once I'm out of the loop, of course, I'm just printing out what x is.

25:47Well, let's try the other scenario that might happen.

25:50Python of number.py, Enter.

25:52What's x?

25:53Let's try cat or any other word.

25:55Enter.

25:56Ah, this is now a new feature.

25:59I'm being informed what I did wrong.

26:01X is not an integer.

26:02So I'm getting some useful user feedback.

26:05But notice, again, I'm prompted, what's x?

26:07Well, let me try typing in dog.

26:09X is not an integer.

26:11What's x?

26:11Let me try bird.

26:13Enter.

26:14X is not an integer.

26:15What's x?

26:15And suffice it to say, this will happen now forever if I'm in an infinite loop

26:19until I try and succeed, at which point I break out.

26:23So let's try again.

26:2450, Enter.

26:25Now I'm out of the loop.

26:26And I'm printing out what x actually is.

26:30All right, let me pause here and see if there are any questions.

26:33The logic is almost the same.

26:35But what is different now is I'm in a loop.

26:38And I'm using the keyword break in Python

26:40to deliberately break out of the loop when I'm

26:43ready to, once the user has cooperated.

26:46AUDIENCE: Do we really need to break?

26:48Can't we just print?

26:51Or what keeps us from just printing?

26:54DAVID MALAN: Good question.

26:55So let me try that.

26:56Couldn't I just print?

26:57Well, let's see what happens if I do that.

26:59Let me move this print line at the end into my loop

27:02here, thereby shortening the program.

27:04And, in general, that's been a good thing.

27:06Python of number.py, Enter.

27:08Let me go ahead and type in 50.

27:10OK, x is 50.

27:11What's x?

27:13OK, maybe it's 49.

27:14X is 49.

27:15OK, maybe 48.

27:17Unfortunately, I think-- you're laughing.

27:19You see it.

27:19I never break out of the loop, which maybe that's a feature.

27:22Maybe you want this to be your program.

27:23But I didn't.

27:24I'd eventually like this game to stop.

27:25So I need to break out in that way.

27:28But I can do it a little differently.

27:29And let me propose that we modify this a little bit.

27:33But, first, any other questions on this syntax here?

27:36Let me rewind to the prior version.

27:41AUDIENCE: Hi, can I use a break [INAUDIBLE] except and else?

27:46For example, in another print, may you use printing the else,

27:51you can use prints together with break or something like this?

27:55DAVID MALAN: So you can use break inside of loops to break out of loops.

27:59And you can use it inside of a conditional,

28:01like an if, an elif, or an else.

28:03You can do it inside of a try, except, else statement to.

28:06Any time you're in a loop that you want to break out

28:09of, you can use this keyword, break.

28:11I'm using it in the context of exceptions.

28:13But it's not restricted to that.

28:14And let me show you, too.

28:15It doesn't even have to be in the else.

28:17If I wanted to, I could actually do this.

28:20I could get rid of my else.

28:21And I could go back to line three, add another line that's indented,

28:26line four, and break out here.

28:28Now, why is this logically OK?

28:31Well, consider what I'm now trying to do.

28:34I'm trying to execute line three and converting the user's input to an int.

28:38And I'm trying to store the result from right to left in x.

28:42If something goes wrong, the code we've already seen

28:45is immediately going to jump to line five

28:48and then six to handle the exception.

28:51But if nothing goes wrong, my code presumably

28:54should just keep on executing line by line.

28:57So I could technically logically put the break here.

29:00And watch what happens when I run this version.

29:02Python of number.py, 50, Enter, it worked.

29:06I broke out of the loop.

29:08Now, which way is better?

29:09Honestly, I think it could go either way at this point.

29:12This program is so relatively short that even

29:15though I'm trying to do two things now, one of which, the break,

29:18is not going to fail.

29:19You either break or you don't.

29:21There's no piece of data from the user that's going to influence that.

29:24We don't strictly need to have those two lines of code there.

29:27But it's only two lines.

29:28So I think it's OK.

29:29And if you recall our discussion in the past, not just of correctness--

29:32does the code work as it should?-- but design,

29:34I think you could argue it either way.

29:36If you prefer the readability of this and the fact

29:38that you don't have an else, that's fine.

29:41If, though, you prefer to minimize just how

29:43many lines of code you're trying to execute in case something goes wrong,

29:47the else is a reasonable approach too.

get_int

29:50Well, allow me to propose, too, now that we refine this further.

29:53I think we're at the point where it's pretty darn correct.

29:56But suppose now that I find myself today and tomorrow

30:00trying to get numbers from the user quite a bit.

30:02It would be nice, as we've seen, to maybe just invent my own function,

30:06get int to get an integer from the user both today and tomorrow and beyond.

30:10And, heck, maybe I can even share that function with other people.

30:12If they want to write programs, they get integers from users.

30:15So how might I go about doing this?

30:17Well, let me go ahead and propose that we do this.

30:19Let me get rid of the print line but keep most of my loop here.

30:22Let me define a function called get int that takes no arguments for now.

30:27And I'm going to go ahead and indent all of the code I already

30:30wrote underneath get int.

30:31So now I have a function called get int that tries to do the following.

30:37Try to get in it from the user.

30:39If something goes wrong and there's a value error,

30:41yell at them with x is not an integer.

30:43Else, break.

30:45But it's not just breaking that I want to do here.

30:47Now that I'm in a function, recall our discussion of return values.

30:51If you're inventing your own function whose purpose in life

30:54isn't just a print something on the screen like a side effect

30:57but is to hand back a value, to hand you back a value,

31:01like on that same post-it note from our discussion of functions,

31:05well, you need to return x explicitly.

31:07How do I now use this function?

31:09Well, as soon as we start making our own functions,

31:11it tends to be convenient to define our own main function as well.

31:14That's the main part of our program.

31:16And I'm going to keep this simple.

31:17I'm now going to say, x equals get int.

31:20And then on the next line, I'm going to do that print from before, quote

31:23unquote, "x is"-- in curly braces--

31:25"x."

31:26And at the very bottom of my program recall,

31:28I'm going to call main, so that no matter what,

31:31I'm invoking my main function after everything's been defined.

31:34Well, let's see how this works.

31:35Let me go ahead and run Python of number.py.

31:39Enter.

31:40Let's type in 50.

31:41And it seems to work as before.

31:43Let's go ahead and run it again, typing in cat, C-A-T, this time.

31:47X is not an integer.

31:48And I'm being prompted.

31:49Dog, and I'm being prompted.

31:51Bird, and I'm being prompted.

31:52Fine, fine, fine.

31:5350.

31:54That's an int.

31:55And so it is printed.

31:57So what's worth noting here-- well, I'm manifesting a couple of good properties

32:00here.

32:01One, I've kind of abstracted away this notion of getting an integer.

32:05And even though I just artificially hit Enter

32:07a whole bunch of times just to hide that function for now--

32:10it needs to be there, but we don't need to see it at this point-- notice

32:13that now this entire program really boils down

32:15to just these three lines of code now.

32:17Why?

32:18Because I've abstracted away that whole process of getting an int from the user

32:22into this new function of my own called get int.

32:25But can I improve upon this?

32:26Well, let me go and undo all of those blank lines

32:29and pull this up just so we can see more on the screen at once.

32:32Can I tighten up my implementation of get int?

32:34It is correct.

32:35I claim this is correct.

32:37It's handling errors.

32:38And it's returning x.

32:39But I don't, strictly speaking, need to write the code as long.

32:43What else could I do?

32:44Well, let me propose that if all you're doing on this line 13 is breaking

32:48and then immediately after that, per the indentation,

32:51you're executing return x on line 14, why are you wasting everyone's time?

32:56Once you know you're ready to return the value, you could just return x.

33:00And so in my else, I could break out and return a value.

33:03So here, too, return is used to return values from functions.

33:08Break is used to break out of loops.

33:11But it turns out that return is sort of stronger than break.

33:15It will not only break you out of a loop.

33:17It will also return a value for you.

33:20So it's doing two things for once, if you will.

33:23But can I make this even more compact?

33:28If my goal is to just tighten the code up, even though it's already correct,

33:32can anyone think of a further refinement,

33:34whether you've programmed in Python before or not?

33:37Can I shorten this implementation further just a little bit,

33:41if only to decrease the probability that I've

33:43made a mistake by having fewer lines and just

33:45make it a little easier to read because it's shorter?

33:49Any suggestions for tightening up my implementation of get int?

33:53AUDIENCE: You can just return the value on the try

33:55function, when you're trying.

33:59You take the input x and then return x.

34:02DAVID MALAN: Good.

34:02We can just return x a little higher up.

34:05And let me correct folks as we go.

34:07It's not a try function.

34:08It would be a try statement, technically.

34:09A function typically has a parentheses and another one.

34:12In this case, it's just a statement.

34:14But we can do exactly that.

34:15I don't technically need the else.

34:17If I really want, I could do this.

34:19Right after line nine, I could return x here.

34:22Or recall our discussion of defining variables unnecessarily sometimes.

34:27Why define a variable here if you're immediately going

34:29to use it here and then never again?

34:31So we could avoid a new line here.

34:33And I could avoid even defining x explicitly.

34:37I could just say something like this.

34:39I could return int, input, quote unquote, "what's x?"

34:42I can do it all at once.

34:44Now, which is better?

34:46I don't know.

34:47I mean, again, this is where reasonable people might disagree.

34:50I'd argue that, on the one hand, we're tightening up the code.

34:53We're using fewer lines.

34:54It's easier to read, lower probability that I've made a mistake.

34:57On the other hand, it's a little more complicated to understand, perhaps.

35:01It's a little less obvious where I'm returning from.

35:04So I think arguments can be made either way.

35:06At the end of the day, what's important is that you've done this consciously.

35:09You've made a decision to do it this way or this way.

35:12And you can justify it in your mind-- not that your answer is, eh, it worked,

35:16so I left it alone.

35:17Have a good reason.

35:18Come up with a good reason.

35:19And that will come with experience and practice.

35:22Well, let me propose to you that we make one other refinement here.

35:25Suppose that you're finding your programs to be a little noisy.

35:28And it's a little obnoxious that you keep telling the user,

35:31x is not an integer.

35:32X is not an integer.

35:33X is not an integer.

35:34What if you want to make things a little gentler and just prompt

35:38the user again with the same words, what's x?

35:41What is x?

35:42What's x?

35:43Again and again.

35:44Well, you can do that as well.

35:45And it turns out that if you want to handle an exception in Python

pass

35:49but you want to pass on doing anything with it-- so you want to catch it,

35:54but you essentially want to ignore it.

35:56You don't want to print anything.

35:57You don't want to quit the program.

35:59You just want to silently ignore it, like

36:02if you're talking in a room full of people and it's your turn to talk

36:05and you're just like, pass.

36:07They're still calling on you.

36:08But you're not doing or saying anything more.

36:10Well, we can add this keyword to our code here.

36:13Let me go back to my program here.

36:15And instead of printing out again and again, x is not an integer,

36:19I could just do this.

36:20I could pass on handling the error further.

36:23I'm still catching it.

36:24So the user is not going to see a scary message even mentioning value error.

36:28My code is catching it.

36:29But I'm passing on saying anything about it.

36:32I'm going to stay in the loop.

36:33I'm going to stay in the loop and keep prompting and reprompting the user

36:36so now the effect looks a little something like this.

36:38Python of number.py.

36:40Let's type in cat.

36:42What's x again?

36:43Let's type in dog.

36:44What's x again?

36:45Type in bird.

36:46So it's just a little, maybe, more user friendly and that you're just

36:49reminding the user what you want.

36:50Maybe it's worse.

36:51Maybe it would be helpful to tell the user why

36:54you're prompting them again and again.

36:56It's not obvious.

36:57So it could go both ways.

36:58But, again, it's just another mechanism, now, for handling these errors.

37:02We use the except keyword to catch a specific error.

37:05But we don't have to handle it more than that.

37:07We can just pass on doing something further.

37:10Let me pause here and see if there's any questions now on try, accept, else,

37:15or pass?

37:17AUDIENCE: OK, yeah.

37:18No.

37:18I was just kind of curious, I guess, about the idea

37:22of when you were inventing with the get int function, for example.

37:27Because I'm noticing, obviously, going through it

37:29with the whole logic and breakdown of the entire function, while true,

37:33do this.

37:34But I'm just kind of curious in elaborating with the indentations

37:37for the code more.

37:38DAVID MALAN: Yeah.

37:39So the invitation is deliberate logically.

37:41Some languages don't require as rigorous indentation.

37:45You can use curly braces or other symbology

37:47to make clear what is associated with what.

37:49In general, any time you indent something in Python on this line--

37:54rather, anytime you write a code a line of code in Python that's here

37:58and the lines below it are somehow indented,

38:00that means that those lines are somehow associated with that first line.

38:04And, presumably, those indented lines should only

38:07be executed if the first line told the computer to do so.

38:13So, concretely, what does this mean?

38:14On line six here, we're defining a function called

38:17get in that takes no arguments, colon.

38:20Everything that's indented by at least four spaces

38:24hereafter is part of that function.

38:26Why?

38:26That's just the design of the Python language.

38:29Frankly, I think the designers got tired of seeing really ugly code in languages

38:33like C and C++ and Java that don't necessarily enforce indentation to this

38:40extent.

38:40So now it's baked into the language.

38:42And my chronology might be a little off there.

38:44But there's been many languages that are looser than Python when

38:47it comes to indentation.

38:48The indentation is meaningful on line seven too.

38:51Notice that because the while true is indented by four spaces.

38:55That just means it's part of the get int function.

38:57But notice below the while true statement, there is eight, there's 12,

39:01there's eight, there's 12 spaces here.

39:03And I'm just quickly counting the dots.

39:05That means that all of the lines I've just highlighted

39:07are inside of that while loop.

39:09While true means to execute lines eight through 11, potentially,

39:13again and again and again.

39:14And now, lastly, on line eight, because we have try and indented below

39:20it is line nine, that just means that what you should try

39:23is what's on line nine.

39:24And similarly, on line 10, below it, we have indented line 11.

39:29You should only pass when there is an exception of a value error.

39:33So the indentation just means what is associated with what.

39:37And once you get comfortable with that, you'll

39:38see that the indentation alone helps explain the logic of your program.

39:43And it has a wonderful side effect that for yourself the next morning,

39:47for your colleagues, your family, your friends, your teachers, your code

39:51is much more readable as a result. It's not one big mess of a blob of text.

39:55Other questions now on try, except, else, or pass?

39:59AUDIENCE: Yeah, thanks.

40:01Two question.

40:02Question one-- once you say pass, can the caller

40:08still learn anything about this era through a system variable or whatever?

40:14And question two-- problem set zero referenced some string methods,

40:19including is numeric--

40:21is it any different to [INAUDIBLE]?

40:27DAVID MALAN: Good question.

40:28So on the first question, if I'm handling the error in this way,

40:30the caller is not going to know anything about it.

40:32That's the point of my handling it, so that main or other callers don't know

40:37that anything technically went wrong.

40:38On the second question, is numeric is another function

40:41that you can call that can look at a string and determine

40:44is this, in fact, a number.

40:46I could use a mechanism like that.

40:48I could use a conditional.

40:50If this looks like a number, then pass it to the int function.

40:54And go ahead and convert it to an integer.

40:56That's totally fine.

40:57I would generally say that the Pythonic way of doing things is often,

41:02for better or for worse, to try things, hope they work.

41:05But if they don't, handle the exception.

41:08So other languages are more in favor of checking if, if, if, if, elif, else,

41:13and all of these conditionals.

41:15Python tends to be a little more of the mindset, eh, try it.

41:19But just make sure you're handling the error.

41:21So this would be the Pythonic way of doing it.

41:23Your way, though-- checking with the conditional, is it a number first?--

41:26is totally reasonable too, if you want to go that way.

41:29Well, let me propose some final refinements

Function Arguments

41:32to this program that really just kind of tighten things up,

41:34one additional step to improve the implementation of this

41:39get int function.

41:40Let me propose that we not hard code, so to speak-- that is type manually x

41:44all over the place.

41:45Let's make this function, get int, a little more reusable.

41:49Right now, notice that I'm just kind of using the honor system that, well, main

41:53is defining a variable called x.

41:55And get int is asking for a variable called x.

41:59But it would be nice if the caller, main,

42:02doesn't have to know what the call-ee is naming its variables and vise versa.

42:07So caller-- to call a function means to use it.

42:09The caller is the function that's using it.

42:11The call-ee is just the function being called.

42:14It would be nice if I'm not just hoping that x is the same in both places.

42:18So let me propose this.

42:20Let me propose that we actually add a parameter to get int, like this.

42:27What's x?

42:28That is to say, if main wants to use the get int function,

42:31well, then main should probably tell the get int function what

42:35prompt to show the user.

42:36Just like the input function, recall, that comes with Python, it's up to you

42:40to pass in a prompt that the user then sees when the human is asked for input.

42:45So how do I make this work here?

42:47I can go down to my definition of get int.

42:49And I can say, all right, get int is going to take a parameter now,

42:53called prompt.

42:53I could call it anything I want.

42:55But prompt in English is pretty self-explanatory.

42:57It means the message the user will see.

42:59And now, down here, when I actually use input,

43:02I don't have to presumptuously say, what's x?

43:05Because what if the program, the caller, wants

43:08to ask for y or z or some other variable?

43:10I can just pass to input whatever prompt the caller has provided.

43:15So now I'm making more reusable code.

43:18It still works just the same.

43:20I haven't changed the functionality, per se.

43:22But now it's a little more dynamic because now

43:24get int doesn't have to know or care what variable's being asked for,

43:28what's being asked for.

43:29It just needs to know what prompt it should show to the user.

43:33So if I now run this program down here, again, prompt number.py, Enter,

43:37what's x?

43:3850 still seems to work.

43:40Let's run it again.

43:41Let's type in cat.

43:42It still seems to work.

43:43And if I type in cat, dog, bird, or anything else,

43:46it will keep prompting me with that same prompt, making this code,

43:49therefore, all the more usable.

43:51Now it turns out, too, you can even raise exceptions yourself

Conclusion

43:55using Python's raise keyword.

43:57But more on that another time.

43:59So in the coming days, the coming weeks, the coming months,

44:01as you write more code in Python, you'll see that errors are inevitable.

44:05Sometimes they're syntax errors, which you've

44:07got to just fix if you even want to run your program at all.

44:10But they could be name errors-- for instance,

44:12variables that you meant to define but somehow didn't-- value errors,

44:15where maybe the user didn't cooperate and provided you with something that

44:19you weren't expecting, or a whole list of other possible errors or exceptions.

44:23But now, hopefully, you know how you can handle these errors

44:26and respond to them in any way you like.

44:29This, then, was our look at exceptions.

44:31And we'll see you next time.

Recently added transcripts

Browse the whole transcript library

This transcript was generated from the captions YouTube publishes for this video. Get the transcript of any YouTube video atfreeyoutubetranscribe.com, free, unlimited, no sign-up.