1 00:00:00,000 --> 00:00:00,984 2 00:00:00,984 --> 00:00:03,936 [MUSIC PLAYING] 3 00:00:03,936 --> 00:00:24,120 4 00:00:24,120 --> 00:00:27,330 DAVID MALAN: All right, this is CS50's introduction 5 00:00:27,330 --> 00:00:28,770 to programming with Python. 6 00:00:28,770 --> 00:00:29,820 My name is David Malan. 7 00:00:29,820 --> 00:00:31,950 And this is our week on exceptions. 8 00:00:31,950 --> 00:00:35,010 Exceptions in Python as well as in other programming languages 9 00:00:35,010 --> 00:00:37,290 refer to problems in your code. 10 00:00:37,290 --> 00:00:40,090 Indeed, when something is exceptional in your program, 11 00:00:40,090 --> 00:00:41,950 it actually doesn't mean it's a good thing. 12 00:00:41,950 --> 00:00:45,518 It means something has gone wrong that, ideally, you will somehow solve. 13 00:00:45,518 --> 00:00:47,560 So what are some of the things that can go wrong? 14 00:00:47,560 --> 00:00:50,520 So I'm going to go ahead and open up VS Code on my computer here. 15 00:00:50,520 --> 00:00:54,638 And in the terminal window, I'm going to go ahead and run code of hello.py. 16 00:00:54,638 --> 00:00:56,430 That's going to, of course, open up a brand 17 00:00:56,430 --> 00:00:59,287 new tab for me, hello.py, in which I can write my code. 18 00:00:59,287 --> 00:01:01,620 And let me go ahead and write some very simple code just 19 00:01:01,620 --> 00:01:03,190 to say hello to the world. 20 00:01:03,190 --> 00:01:05,430 Let's go ahead and say print "hello, world. 21 00:01:05,430 --> 00:01:08,130 22 00:01:08,130 --> 00:01:10,470 And then let me go ahead and-- 23 00:01:10,470 --> 00:01:12,420 I'm forgetting to close that quote. 24 00:01:12,420 --> 00:01:14,670 So a mistake that you yourself might have already made 25 00:01:14,670 --> 00:01:17,370 or might surely in the future make-- and it's a little subtle 26 00:01:17,370 --> 00:01:19,320 because you might not necessarily notice that you've just 27 00:01:19,320 --> 00:01:20,580 missed that one character. 28 00:01:20,580 --> 00:01:23,400 Well, let me go ahead and somewhat optimistically 29 00:01:23,400 --> 00:01:28,200 go down to my terminal window now and run Python of hello.py and hit Enter. 30 00:01:28,200 --> 00:01:29,970 And that's the first of my errors. 31 00:01:29,970 --> 00:01:31,830 My gosh, I've only written one line of code. 32 00:01:31,830 --> 00:01:34,350 And I seem to have more lines of errors on the screen. 33 00:01:34,350 --> 00:01:37,090 But the salient point is this bottom-most thing here. 34 00:01:37,090 --> 00:01:39,030 Notice where it says syntax error. 35 00:01:39,030 --> 00:01:43,140 A syntax error is a problem with the code that you have typed, your syntax. 36 00:01:43,140 --> 00:01:45,000 Just like English and other human languages 37 00:01:45,000 --> 00:01:47,670 have syntax associated with them, so does my code. 38 00:01:47,670 --> 00:01:49,170 And it's not quite correct. 39 00:01:49,170 --> 00:01:50,370 Something is awry. 40 00:01:50,370 --> 00:01:52,380 I didn't follow the instructions properly. 41 00:01:52,380 --> 00:01:56,130 And it does elaborate for me, unterminated string literal. 42 00:01:56,130 --> 00:01:57,360 Now, that's a bit arcane. 43 00:01:57,360 --> 00:01:59,370 That is a bit of a confusing error message. 44 00:01:59,370 --> 00:02:01,800 But unterminated would generally mean that I 45 00:02:01,800 --> 00:02:03,960 started something but didn't stop it. 46 00:02:03,960 --> 00:02:05,070 I didn't terminate it. 47 00:02:05,070 --> 00:02:08,310 String, of course, is a sequence of text, like we've discussed before-- 48 00:02:08,310 --> 00:02:09,750 or stir in Python. 49 00:02:09,750 --> 00:02:13,020 And literal generally refers to something that you literally typed. 50 00:02:13,020 --> 00:02:14,100 It's not a variable. 51 00:02:14,100 --> 00:02:15,990 It's something like quote unquote-- 52 00:02:15,990 --> 00:02:18,120 or just "hello world. 53 00:02:18,120 --> 00:02:20,790 So the fix here, of course, is going to be 54 00:02:20,790 --> 00:02:24,660 to go ahead and terminate that string and actually close the quote. 55 00:02:24,660 --> 00:02:27,150 And if I now go back down into my terminal window 56 00:02:27,150 --> 00:02:31,870 and rerun Python of hello.py, now I'm saying hello to the world. 57 00:02:31,870 --> 00:02:36,510 So the catch with syntax errors here is that syntax errors are entirely 58 00:02:36,510 --> 00:02:37,560 on you to solve. 59 00:02:37,560 --> 00:02:40,560 A syntax error is a problem that you've got to go back into your code 60 00:02:40,560 --> 00:02:41,760 and fix from the get-go. 61 00:02:41,760 --> 00:02:43,890 You can't just kind of hope that it's going 62 00:02:43,890 --> 00:02:47,280 to resolve itself or expect that other parts of your code 63 00:02:47,280 --> 00:02:48,300 will catch it for you. 64 00:02:48,300 --> 00:02:50,610 Syntax errors just must be fixed. 65 00:02:50,610 --> 00:02:53,340 But there's a lot of other types of errors in Python 66 00:02:53,340 --> 00:02:55,920 that might be described as runtime errors, that 67 00:02:55,920 --> 00:02:57,940 happen while your code is running. 68 00:02:57,940 --> 00:03:01,680 And it's really up to you to write some additional code defensively 69 00:03:01,680 --> 00:03:05,320 to detect when those errors happen because you don't necessarily know, 70 00:03:05,320 --> 00:03:08,590 for instance, what input humans are going to type into your program. 71 00:03:08,590 --> 00:03:11,760 And so you better be ready, defensively, to accommodate things 72 00:03:11,760 --> 00:03:13,830 that they type or even misstype. 73 00:03:13,830 --> 00:03:17,100 So, for instance, let's go back over here to VS Code. 74 00:03:17,100 --> 00:03:20,730 And let me propose that we take a look at a new file all together. 75 00:03:20,730 --> 00:03:22,290 I'm going to close hello.py. 76 00:03:22,290 --> 00:03:26,160 And I'm going to write code of say number.py. 77 00:03:26,160 --> 00:03:28,710 So let's play around with some numbers in Python. 78 00:03:28,710 --> 00:03:32,670 And the first thing I'm going to go ahead here and do with number.py, 79 00:03:32,670 --> 00:03:35,970 after opening this new tab, is I think I'm going to go ahead and print-- 80 00:03:35,970 --> 00:03:40,350 type up a relatively simple program that maybe prompts the user for an integer, 81 00:03:40,350 --> 00:03:43,000 like x, and then just prints out what x is. 82 00:03:43,000 --> 00:03:45,930 So we're going to start simple, but, again, in starting simple, 83 00:03:45,930 --> 00:03:48,870 we'll be able to really see where I've done something wrong. 84 00:03:48,870 --> 00:03:49,600 Well, here we go. 85 00:03:49,600 --> 00:03:51,780 I'm going to go ahead and say a variable called 86 00:03:51,780 --> 00:03:57,330 x is going to get assigned the value of the return value of input, 87 00:03:57,330 --> 00:03:59,603 quote unquote, "what's x?" 88 00:03:59,603 --> 00:04:02,520 And I'm going to include a space to move the cursor over a little bit. 89 00:04:02,520 --> 00:04:05,550 And then, ultimately, I'm going to go ahead and-- oh, wait a minute. 90 00:04:05,550 --> 00:04:08,070 If I'm wanting to get an int from the user, 91 00:04:08,070 --> 00:04:10,530 recall that I need to do something proactively. 92 00:04:10,530 --> 00:04:14,760 I need to actually convert that input to an integer using 93 00:04:14,760 --> 00:04:16,050 the int function in Python. 94 00:04:16,050 --> 00:04:20,519 So now I'm passing the return value of input as the argument to int. 95 00:04:20,519 --> 00:04:22,980 And that will store in x, ultimately, an integer, not 96 00:04:22,980 --> 00:04:24,893 a string that looks like an integer. 97 00:04:24,893 --> 00:04:28,060 All right, let me go ahead now and just quite simply print out what this is. 98 00:04:28,060 --> 00:04:32,610 I'm going to go ahead and print out, quote unquote, "x is x." 99 00:04:32,610 --> 00:04:34,920 But I don't want to literally say x is x. 100 00:04:34,920 --> 00:04:36,390 I want to plug in the value of x. 101 00:04:36,390 --> 00:04:40,020 So maybe the easiest way to do that is to surround it with curly braces. 102 00:04:40,020 --> 00:04:42,360 And then if I'm using these curly braces and I 103 00:04:42,360 --> 00:04:45,630 want Python to interpolate the value of that variable, 104 00:04:45,630 --> 00:04:49,440 that is substitute what x actually is in between those curly braces, 105 00:04:49,440 --> 00:04:52,170 recall that I need to use a format string or an F-string 106 00:04:52,170 --> 00:04:56,520 by fixing this whole thing with an F. Now that I've done that, let's go ahead 107 00:04:56,520 --> 00:04:57,640 and see what happens. 108 00:04:57,640 --> 00:05:02,010 I'm going to go ahead in my terminal window and run Python of number.py. 109 00:05:02,010 --> 00:05:02,760 I hit Enter. 110 00:05:02,760 --> 00:05:03,750 And so far, so good. 111 00:05:03,750 --> 00:05:05,580 All is well and being prompted for x. 112 00:05:05,580 --> 00:05:08,330 Let me go ahead and type in a number like 50. 113 00:05:08,330 --> 00:05:09,840 All right, that seems to work. 114 00:05:09,840 --> 00:05:12,610 Program seems to be correct. 115 00:05:12,610 --> 00:05:14,620 Or is it? 116 00:05:14,620 --> 00:05:19,610 What could go wrong in this program, even though nothing did just go wrong? 117 00:05:19,610 --> 00:05:22,630 But if I run it and run it and run it again, 118 00:05:22,630 --> 00:05:26,090 during the running of my program, what could still go wrong, 119 00:05:26,090 --> 00:05:28,660 especially if I'm not the human interacting with it 120 00:05:28,660 --> 00:05:30,910 but some other human instead? 121 00:05:30,910 --> 00:05:33,910 Any volunteers here for this one? 122 00:05:33,910 --> 00:05:35,780 What could go wrong? 123 00:05:35,780 --> 00:05:40,300 And in what way is this program not really correct, even 124 00:05:40,300 --> 00:05:42,530 though at first glance it seems so. 125 00:05:42,530 --> 00:05:44,170 AUDIENCE: [INAUDIBLE] 126 00:05:44,170 --> 00:05:52,890 127 00:05:52,890 --> 00:05:54,990 DAVID MALAN: So I'm not calling an integer. 128 00:05:54,990 --> 00:05:56,532 I'm still having trouble hearing you. 129 00:05:56,532 --> 00:05:59,560 But what I think I heard is that if what the user types in is not, 130 00:05:59,560 --> 00:06:03,797 in fact, an integer, I can't just blindly convert it to an int. 131 00:06:03,797 --> 00:06:05,880 If I'm not putting too many words into your mouth, 132 00:06:05,880 --> 00:06:10,740 I think what I should perhaps do here is be a little defensive. 133 00:06:10,740 --> 00:06:14,040 And let me see if I can't simulate exactly the problem that 134 00:06:14,040 --> 00:06:14,920 could go wrong here. 135 00:06:14,920 --> 00:06:18,000 Let me go ahead and run, again, Python of number.py. 136 00:06:18,000 --> 00:06:19,290 Let me try another number. 137 00:06:19,290 --> 00:06:21,480 In fact, when testing your code, generally it's 138 00:06:21,480 --> 00:06:25,920 a good idea to test corner cases, maybe numbers that aren't quite as plain as 139 00:06:25,920 --> 00:06:27,907 or 49 or 51. 140 00:06:27,907 --> 00:06:30,990 Let's choose some numbers that might be a little more interesting, if only 141 00:06:30,990 --> 00:06:32,610 mathematically, like zero. 142 00:06:32,610 --> 00:06:34,050 All right, zero seems to work. 143 00:06:34,050 --> 00:06:35,880 My code still prints out that x is zero. 144 00:06:35,880 --> 00:06:37,890 What might be another corner case to consider? 145 00:06:37,890 --> 00:06:39,890 Well, let me go ahead and try a negative number. 146 00:06:39,890 --> 00:06:42,770 That, too, is pretty different in spirit from negative. 147 00:06:42,770 --> 00:06:43,680 Negative 1? 148 00:06:43,680 --> 00:06:44,880 OK, that works too. 149 00:06:44,880 --> 00:06:46,410 Well, let me try it one more time. 150 00:06:46,410 --> 00:06:48,990 I've tried positive numbers, negative numbers, 0. 151 00:06:48,990 --> 00:06:50,950 Let me try something like a cat. 152 00:06:50,950 --> 00:06:56,010 So literally, C-A-T-- typing in a string that doesn't even look like a number. 153 00:06:56,010 --> 00:06:58,950 And yet, let's see now what happens when I hit Enter. 154 00:06:58,950 --> 00:07:01,560 All right, we'll see now we've got another kind of error. 155 00:07:01,560 --> 00:07:05,310 It's not a syntax error, because I didn't make a typographical mistake. 156 00:07:05,310 --> 00:07:07,620 I didn't forget some piece of syntax. 157 00:07:07,620 --> 00:07:10,905 I actually now have an error with one of my values. 158 00:07:10,905 --> 00:07:12,780 And it's an a value I didn't even anticipate. 159 00:07:12,780 --> 00:07:17,200 The human, me, in this case typed it in long after I wrote the code. 160 00:07:17,200 --> 00:07:18,540 So what does this refer to? 161 00:07:18,540 --> 00:07:19,590 A value error. 162 00:07:19,590 --> 00:07:21,270 Well, let's see what the explanation is. 163 00:07:21,270 --> 00:07:25,375 Invalid literal for int with base 10, quote unquote, "cat." 164 00:07:25,375 --> 00:07:27,000 Now, this, too, is a bit of a mouthful. 165 00:07:27,000 --> 00:07:29,910 And, unfortunately, in Python and a lot of programming languages, 166 00:07:29,910 --> 00:07:32,817 the error messages are written for pretty comfortable programmers. 167 00:07:32,817 --> 00:07:35,650 And, of course, when you're learning programming for the first time, 168 00:07:35,650 --> 00:07:38,192 you might not be so comfortable with the programming language 169 00:07:38,192 --> 00:07:40,000 let alone the error messages. 170 00:07:40,000 --> 00:07:42,370 But let's see if we can't glean some insight. 171 00:07:42,370 --> 00:07:43,830 So invalid literal. 172 00:07:43,830 --> 00:07:47,410 Well, again, a literal is just something that's been typed in, it would seem, 173 00:07:47,410 --> 00:07:48,360 for int. 174 00:07:48,360 --> 00:07:50,220 What is int exactly? 175 00:07:50,220 --> 00:07:52,680 Well, int is the function I'm using to convert the user's 176 00:07:52,680 --> 00:07:55,200 input to a corresponding integer. 177 00:07:55,200 --> 00:07:58,260 Base 10, that refers to the decimal system, which is this 178 00:07:58,260 --> 00:07:59,970 the default that Python is using. 179 00:07:59,970 --> 00:08:02,460 And it looks like at the end of the day, what Python really 180 00:08:02,460 --> 00:08:07,570 doesn't like is that I passed cat, quote unquote, "to the int function." 181 00:08:07,570 --> 00:08:10,890 So how do I go about actually fixing this problem? 182 00:08:10,890 --> 00:08:13,862 Well, I could just add instructions in my program. 183 00:08:13,862 --> 00:08:15,570 Maybe I could add a line of print telling 184 00:08:15,570 --> 00:08:18,720 the user more explicitly, be sure to type an integer, 185 00:08:18,720 --> 00:08:20,220 or, please don't type cat. 186 00:08:20,220 --> 00:08:21,750 Please don't type strings. 187 00:08:21,750 --> 00:08:23,670 Of course, the user might still not oblige. 188 00:08:23,670 --> 00:08:25,420 They might not be reading the instruction. 189 00:08:25,420 --> 00:08:27,600 So that too is probably not an effective strategy. 190 00:08:27,600 --> 00:08:31,278 What we really want to do is write our code with error handling in mind. 191 00:08:31,278 --> 00:08:33,570 We want to write lines of code that not only accomplish 192 00:08:33,570 --> 00:08:36,539 the problems we care about but that also handle 193 00:08:36,539 --> 00:08:39,299 errors that might unexpectedly happen. 194 00:08:39,299 --> 00:08:41,970 And, in general, when programming, programming defensively. 195 00:08:41,970 --> 00:08:44,910 Assume that the users aren't going to be paying attention or, worse, 196 00:08:44,910 --> 00:08:45,850 they're malicious. 197 00:08:45,850 --> 00:08:47,920 They're trying to crash your program. 198 00:08:47,920 --> 00:08:50,280 So we want to handle as many errors as we can. 199 00:08:50,280 --> 00:08:52,470 Now, how do we go about doing that in Python? 200 00:08:52,470 --> 00:08:56,850 Well, it turns out whether you want to catch a value error or other types 201 00:08:56,850 --> 00:08:59,250 of errors as well-- though not syntax error-- 202 00:08:59,250 --> 00:09:01,620 Python actually has this keyword called try. 203 00:09:01,620 --> 00:09:02,910 And it's sort of aptly named. 204 00:09:02,910 --> 00:09:05,700 If you want to try to do something in Python, 205 00:09:05,700 --> 00:09:07,680 you can literally use this keyword. 206 00:09:07,680 --> 00:09:11,430 And you can check whether or not something exceptional, something 207 00:09:11,430 --> 00:09:12,840 erroneous, has happened. 208 00:09:12,840 --> 00:09:16,140 So using both try and this other keyword, except, 209 00:09:16,140 --> 00:09:20,400 can I go and try to do something except if something goes wrong? 210 00:09:20,400 --> 00:09:22,510 I can do something else instead. 211 00:09:22,510 --> 00:09:25,020 So let's consider, how can I go about trying 212 00:09:25,020 --> 00:09:29,010 to convert the user's input to an int except if something goes wrong? 213 00:09:29,010 --> 00:09:31,200 Well, let me go back to my code here. 214 00:09:31,200 --> 00:09:34,750 And let me propose that I now modify this example as follows. 215 00:09:34,750 --> 00:09:37,320 Let me go ahead and, above my first line of code, 216 00:09:37,320 --> 00:09:40,500 I literally write, try and a colon, telling Python, 217 00:09:40,500 --> 00:09:42,160 try to do the following. 218 00:09:42,160 --> 00:09:44,700 I'm going to go ahead and indent my existing lines of codes 219 00:09:44,700 --> 00:09:47,770 here by the same number of spaces, four in this case. 220 00:09:47,770 --> 00:09:51,060 And then I'm going to add one more new line down here that literally says, 221 00:09:51,060 --> 00:09:53,352 except Value Error. 222 00:09:53,352 --> 00:09:55,560 And notice it's important that I've capitalized the V 223 00:09:55,560 --> 00:09:59,460 and I've capitalized the E. These symbols are case sensitive. 224 00:09:59,460 --> 00:10:02,730 And this is now an opportunity, after this colon, 225 00:10:02,730 --> 00:10:07,230 to tell Python what I want to do in exceptional cases, when 226 00:10:07,230 --> 00:10:10,920 the number or the input from the user is not, in fact, a number. 227 00:10:10,920 --> 00:10:13,860 And I'm going to say something plain like print, quote unquote, 228 00:10:13,860 --> 00:10:15,750 "x is not an integer." 229 00:10:15,750 --> 00:10:19,750 I'm at least going to tell the user roughly what the problem actually is. 230 00:10:19,750 --> 00:10:21,030 So notice another detail. 231 00:10:21,030 --> 00:10:22,620 The indentation is important. 232 00:10:22,620 --> 00:10:26,970 Because I have try on line one and I've indented lines two and three, those 233 00:10:26,970 --> 00:10:30,990 are the two lines of code that I'm trying, except if I see a value error, 234 00:10:30,990 --> 00:10:33,630 line five, because it's indented is what is 235 00:10:33,630 --> 00:10:36,790 going to get executed in cases of those errors. 236 00:10:36,790 --> 00:10:43,920 Let me go ahead now back to my terminal window and run Python of number.py, 237 00:10:43,920 --> 00:10:44,490 Enter. 238 00:10:44,490 --> 00:10:47,130 And let's go ahead and type in again. 239 00:10:47,130 --> 00:10:48,270 Still seems to work. 240 00:10:48,270 --> 00:10:50,302 And, of course, I'm trying and succeeding. 241 00:10:50,302 --> 00:10:53,260 Let me go ahead and try once more, this time, though, with the word cat 242 00:10:53,260 --> 00:10:55,450 or, really, anything that's not a decimal number. 243 00:10:55,450 --> 00:10:59,680 And now you'll see much more cleanly x is not an integer. 244 00:10:59,680 --> 00:11:02,350 I'm not seeing some scary error message that I, the user, 245 00:11:02,350 --> 00:11:04,330 am going to have no idea how to handle. 246 00:11:04,330 --> 00:11:06,640 Now you, the programmer, have anticipated 247 00:11:06,640 --> 00:11:08,290 that something exceptional can happen. 248 00:11:08,290 --> 00:11:12,850 And you've gone about actually handling the error for the user, 249 00:11:12,850 --> 00:11:15,490 giving them an appropriate error message instead. 250 00:11:15,490 --> 00:11:18,340 Let me pause here and see, are there any questions now 251 00:11:18,340 --> 00:11:21,190 on what we've just done by introducing try 252 00:11:21,190 --> 00:11:25,370 and accept to handle this value error? 253 00:11:25,370 --> 00:11:28,380 AUDIENCE: Is value ever the only type of error you can get? 254 00:11:28,380 --> 00:11:29,610 Or are there other types? 255 00:11:29,610 --> 00:11:31,380 DAVID MALAN: Is value error the only thing you can catch? 256 00:11:31,380 --> 00:11:32,590 There are other errors as well. 257 00:11:32,590 --> 00:11:33,930 And we'll see a few of them today. 258 00:11:33,930 --> 00:11:36,270 And there's many, many more, honestly, that if you continue 259 00:11:36,270 --> 00:11:38,145 programming and programming in Python, you're 260 00:11:38,145 --> 00:11:41,710 going to see a lot of them over the weeks the months the years to come. 261 00:11:41,710 --> 00:11:43,830 But the technique for handling them is going 262 00:11:43,830 --> 00:11:47,490 to be largely the same other questions on try, accept, 263 00:11:47,490 --> 00:11:49,260 or these exceptions more generally? 264 00:11:49,260 --> 00:11:51,210 AUDIENCE: Yes, sir. 265 00:11:51,210 --> 00:11:55,980 Actually, to use the except block, you need to know the type of error, right? 266 00:11:55,980 --> 00:12:01,150 [INAUDIBLE] what if you can't anticipate this particular type of error? 267 00:12:01,150 --> 00:12:02,650 DAVID MALAN: A really good question. 268 00:12:02,650 --> 00:12:06,330 So I'm being very good about catching, so to speak, 269 00:12:06,330 --> 00:12:08,793 the very error that I might happen. 270 00:12:08,793 --> 00:12:10,710 I don't know when it might happen because it's 271 00:12:10,710 --> 00:12:11,877 going to depend on the user. 272 00:12:11,877 --> 00:12:15,180 But I know what kind of error will happen from the int function. 273 00:12:15,180 --> 00:12:19,590 There is a way in Python where you can say, except if anything goes wrong. 274 00:12:19,590 --> 00:12:23,440 And you can literally omit value error and just catch everything. 275 00:12:23,440 --> 00:12:27,660 The problem with that is that it sometimes hides other bugs in your code 276 00:12:27,660 --> 00:12:29,952 because you don't necessarily know what's going wrong. 277 00:12:29,952 --> 00:12:32,160 And if you don't necessarily know what's going wrong, 278 00:12:32,160 --> 00:12:34,300 how can you possibly handle it correctly? 279 00:12:34,300 --> 00:12:35,490 So bad practice. 280 00:12:35,490 --> 00:12:38,940 And it put another way, it's lazy to do that, to just say, catch everything 281 00:12:38,940 --> 00:12:40,140 and I'll deal with it here. 282 00:12:40,140 --> 00:12:43,740 So a much better practice would be to figure out what kind of errors 283 00:12:43,740 --> 00:12:48,210 could happen and include mention of them explicitly, as I have done. 284 00:12:48,210 --> 00:12:51,390 Now, with that said, if you read Python's official documentation, 285 00:12:51,390 --> 00:12:54,120 as you'll eventually invariably do, it is not 286 00:12:54,120 --> 00:12:58,080 great about telling you proactively what kinds of errors 287 00:12:58,080 --> 00:13:00,390 can be raised in this way. 288 00:13:00,390 --> 00:13:03,270 So it's a bit of contradictory advice. 289 00:13:03,270 --> 00:13:04,620 You should do it this way. 290 00:13:04,620 --> 00:13:07,470 But it's not always obvious what you should be checking for. 291 00:13:07,470 --> 00:13:09,420 But you get better at it with practice. 292 00:13:09,420 --> 00:13:12,760 And some of the times, the documentation does spell out what could go wrong. 293 00:13:12,760 --> 00:13:14,610 Let me turn our attention now back to this 294 00:13:14,610 --> 00:13:17,790 and point out that even though this is better code, 295 00:13:17,790 --> 00:13:21,450 it is more correct in the sense that I'm not just leaving it to the user 296 00:13:21,450 --> 00:13:25,410 to see some really ugly default Python error message that most people are 297 00:13:25,410 --> 00:13:27,600 going to have no idea what to do with, I'm 298 00:13:27,600 --> 00:13:29,100 at least handling it more elegantly. 299 00:13:29,100 --> 00:13:31,570 And I'm printing out x is not an integer. 300 00:13:31,570 --> 00:13:33,000 So it's at least more instructive. 301 00:13:33,000 --> 00:13:36,150 But this isn't necessarily the best way to implement this code. 302 00:13:36,150 --> 00:13:36,720 Why? 303 00:13:36,720 --> 00:13:39,780 Well, here, too, I'm actually still being a little lazy. 304 00:13:39,780 --> 00:13:44,190 So notice that I'm trying to do not one line of code but two lines of code. 305 00:13:44,190 --> 00:13:47,820 And this isn't a huge deal because we're only talking about two lines of code. 306 00:13:47,820 --> 00:13:51,000 But in the interest of preaching best practices, 307 00:13:51,000 --> 00:13:56,940 you should really only be trying to do the one or very few lines of code that 308 00:13:56,940 --> 00:14:01,740 can actually raise an exception that can actually fail in some way. 309 00:14:01,740 --> 00:14:06,900 I am pretty sure that calling print here is not going to raise a value error. 310 00:14:06,900 --> 00:14:10,740 Whether x is an int or a string or a float or anything else, 311 00:14:10,740 --> 00:14:15,010 the format string feature of Python is going to handle printing it just fine. 312 00:14:15,010 --> 00:14:17,290 So, really, what I'm going to do is this. 313 00:14:17,290 --> 00:14:21,420 I'm going to move this line three down to the bottom of my code. 314 00:14:21,420 --> 00:14:22,830 I no longer need to indent it. 315 00:14:22,830 --> 00:14:26,460 I'm just going to execute it at the bottom of my file here. 316 00:14:26,460 --> 00:14:28,710 Unfortunately, by doing this-- 317 00:14:28,710 --> 00:14:32,610 I've done a good thing by now only trying to do the minimal amount of work 318 00:14:32,610 --> 00:14:36,450 necessary that might raise the exception of value error. 319 00:14:36,450 --> 00:14:38,873 But I fear I've introduced a new mistake. 320 00:14:38,873 --> 00:14:39,540 Well, let's see. 321 00:14:39,540 --> 00:14:40,950 What is now incorrect? 322 00:14:40,950 --> 00:14:44,490 Let me go ahead and again run Python of number.py, Enter. 323 00:14:44,490 --> 00:14:46,755 Let me go ahead and do it correctly with 50. 324 00:14:46,755 --> 00:14:48,340 And all seems to be well. 325 00:14:48,340 --> 00:14:50,190 But, again, let's try those corner cases-- 326 00:14:50,190 --> 00:14:52,920 the zeros, the negative numbers, or, in this case, the cat. 327 00:14:52,920 --> 00:14:55,230 Let me go ahead and type in C-A-T again. 328 00:14:55,230 --> 00:14:55,950 Enter. 329 00:14:55,950 --> 00:14:57,610 Now I have a name error. 330 00:14:57,610 --> 00:15:01,350 So now it's yet another type of error in my code that I've introduced here. 331 00:15:01,350 --> 00:15:03,180 And what does this name error mean? 332 00:15:03,180 --> 00:15:07,140 Well, just as a value error refers to that-- the value of some variable, 333 00:15:07,140 --> 00:15:09,240 the value that someone has typed in is incorrect-- 334 00:15:09,240 --> 00:15:13,500 name error tends to refer to your code, like you're doing something with 335 00:15:13,500 --> 00:15:16,350 the name of a variable that you shouldn't. 336 00:15:16,350 --> 00:15:17,350 And why might that be? 337 00:15:17,350 --> 00:15:19,350 Well, let me turn our attention back to the code 338 00:15:19,350 --> 00:15:22,500 here and consider, what is it complaining about? 339 00:15:22,500 --> 00:15:24,630 Well, the name errors what I see down here. 340 00:15:24,630 --> 00:15:28,710 And it's telling me, name, quote unquote, "x is not defined." 341 00:15:28,710 --> 00:15:31,950 And notice if I look further here, it is mentioning line six. 342 00:15:31,950 --> 00:15:35,610 So I know the problem is with my code on line six. 343 00:15:35,610 --> 00:15:38,460 And that worked a moment ago. 344 00:15:38,460 --> 00:15:42,210 And I'm defining x on line two. 345 00:15:42,210 --> 00:15:48,750 But let me ask the group here, why does x, in fact, exist online six? 346 00:15:48,750 --> 00:15:52,200 Why is it not defined, even though I'm pretty sure I 347 00:15:52,200 --> 00:15:54,920 was intending to define it on line two? 348 00:15:54,920 --> 00:16:00,330 AUDIENCE: Maybe the scope of the variable is between the [INAUDIBLE].. 349 00:16:00,330 --> 00:16:02,130 DAVID MALAN: So, good terminology. 350 00:16:02,130 --> 00:16:06,270 Scope refers to the portion of code in which a variable exists. 351 00:16:06,270 --> 00:16:08,340 That, too, though isn't quite right in Python. 352 00:16:08,340 --> 00:16:12,990 That would be true in C, C++, and Java, where indentation or curly braces tend 353 00:16:12,990 --> 00:16:15,120 to define the scope of a variable. 354 00:16:15,120 --> 00:16:16,770 But, again, here in general-- 355 00:16:16,770 --> 00:16:18,420 and this worked a moment ago. 356 00:16:18,420 --> 00:16:22,110 X exists once it's defined on line two because, remember, 357 00:16:22,110 --> 00:16:24,630 I printed out x is 50 a little bit ago. 358 00:16:24,630 --> 00:16:27,990 Let's try one more hypothesis here. 359 00:16:27,990 --> 00:16:29,760 One more hand? 360 00:16:29,760 --> 00:16:32,970 Why is x somehow still not defined? 361 00:16:32,970 --> 00:16:36,400 AUDIENCE: Yeah, so is it because it's local variable, 362 00:16:36,400 --> 00:16:39,320 meaning that it doesn't define outside of the scope 363 00:16:39,320 --> 00:16:42,570 because what people have mentioned. 364 00:16:42,570 --> 00:16:45,150 It prompts the input in try, right? 365 00:16:45,150 --> 00:16:46,818 The outside of it is undefined. 366 00:16:46,818 --> 00:16:48,360 DAVID MALAN: So still good instincts. 367 00:16:48,360 --> 00:16:49,710 And good terminology, too. 368 00:16:49,710 --> 00:16:52,800 There's this notion of local variables, which tend to exist inside 369 00:16:52,800 --> 00:16:55,080 of functions, for instance, global variables, 370 00:16:55,080 --> 00:16:57,150 which tend to exist in entire files. 371 00:16:57,150 --> 00:16:59,860 In this case, too, though, that's not quite the case. 372 00:16:59,860 --> 00:17:03,060 What's happening here boils down to order of operations. 373 00:17:03,060 --> 00:17:06,060 Let me come back to the code here and recall that any time we've 374 00:17:06,060 --> 00:17:09,510 discussed the assignment operator, the single equal sign, that copies 375 00:17:09,510 --> 00:17:11,280 a value from the right to the left. 376 00:17:11,280 --> 00:17:14,670 But consider for a moment at what point something is going wrong. 377 00:17:14,670 --> 00:17:17,819 Well, the input function is probably working just fine 378 00:17:17,819 --> 00:17:20,310 because we've used that a lot now to get users' input. 379 00:17:20,310 --> 00:17:24,150 It always returns a string or a stir in Python. 380 00:17:24,150 --> 00:17:25,650 But what could be going wrong? 381 00:17:25,650 --> 00:17:32,310 Well, if I'm passing that string to the int function as its argument, 382 00:17:32,310 --> 00:17:34,920 it's probably the int's function that's erroring. 383 00:17:34,920 --> 00:17:37,830 And, indeed, if you think back earlier when we had the value error, 384 00:17:37,830 --> 00:17:39,930 it was, in fact, the int function that did not 385 00:17:39,930 --> 00:17:42,520 like, quote unquote, "cat" as input. 386 00:17:42,520 --> 00:17:45,420 So this is all to say that this portion of my code 387 00:17:45,420 --> 00:17:48,870 highlighted now to the right of the equal sign, that's 388 00:17:48,870 --> 00:17:50,700 the code that's creating a problem. 389 00:17:50,700 --> 00:17:53,410 That's the code that was creating a value error. 390 00:17:53,410 --> 00:17:57,000 And in this case, we're catching the value error. 391 00:17:57,000 --> 00:18:01,170 But because the value error is happening on the right of the equal sign, 392 00:18:01,170 --> 00:18:03,780 there's no value being copied to the left. 393 00:18:03,780 --> 00:18:06,370 The error is interrupting that whole process. 394 00:18:06,370 --> 00:18:10,530 So even though we see x equals dot dot dot on line two, 395 00:18:10,530 --> 00:18:13,200 the portion of that line to the left of the equal sign 396 00:18:13,200 --> 00:18:16,140 isn't getting evaluated, ultimately, because the value 397 00:18:16,140 --> 00:18:18,300 error is happening too soon. 398 00:18:18,300 --> 00:18:20,988 And so when we finally get down to line six, 399 00:18:20,988 --> 00:18:23,280 even though it looked like I was defining on line two-- 400 00:18:23,280 --> 00:18:26,160 and I would have defined x on line two if all had gone well-- 401 00:18:26,160 --> 00:18:29,470 we didn't get to the part where the value is copied from right to left 402 00:18:29,470 --> 00:18:31,570 because the value error happened first. 403 00:18:31,570 --> 00:18:34,350 So this code is just incorrect now. 404 00:18:34,350 --> 00:18:37,090 So how do I go about solving something like this? 405 00:18:37,090 --> 00:18:41,190 Well, it turns out that there's another feature of the try 406 00:18:41,190 --> 00:18:43,650 and accept syntax that Python supports, which is 407 00:18:43,650 --> 00:18:46,260 that it also supports the keyword else. 408 00:18:46,260 --> 00:18:47,970 Now, we've seen else before. 409 00:18:47,970 --> 00:18:51,000 If you think back to our discussion of conditionals, we saw if. 410 00:18:51,000 --> 00:18:52,290 We saw elif. 411 00:18:52,290 --> 00:18:55,260 We saw else, which was kind of this catchall, what 412 00:18:55,260 --> 00:18:58,200 you should do in the event that nothing else is relevant. 413 00:18:58,200 --> 00:19:02,760 That's kind of the same intuition here for the try-except feature of Python. 414 00:19:02,760 --> 00:19:04,560 What you can do is this. 415 00:19:04,560 --> 00:19:09,450 You can try to do the following, as I've done, except if this goes wrong. 416 00:19:09,450 --> 00:19:13,420 But if nothing goes wrong, else go ahead and do this. 417 00:19:13,420 --> 00:19:16,620 So this is one way I can solve this same problem now. 418 00:19:16,620 --> 00:19:21,030 No matter what now, Python is going to try to execute line two. 419 00:19:21,030 --> 00:19:24,030 If something goes wrong, it's going to execute lines three 420 00:19:24,030 --> 00:19:26,500 and four to handle that value error. 421 00:19:26,500 --> 00:19:30,340 However, if you try and this code succeeds, 422 00:19:30,340 --> 00:19:32,880 then there is no exception to handle. 423 00:19:32,880 --> 00:19:35,697 So you're then going to execute this line here. 424 00:19:35,697 --> 00:19:37,530 So it's a little confusing, perhaps, in that 425 00:19:37,530 --> 00:19:41,430 we're now using else both for conditionals-- if, elif, elif, elif, 426 00:19:41,430 --> 00:19:42,060 else. 427 00:19:42,060 --> 00:19:45,840 And we're also using else with these try-except blocks. 428 00:19:45,840 --> 00:19:46,690 But that's OK. 429 00:19:46,690 --> 00:19:47,580 That's part of the language. 430 00:19:47,580 --> 00:19:48,705 That's one of the features. 431 00:19:48,705 --> 00:19:54,330 So now if I rerun this code in my terminal window, Python of number.py-- 432 00:19:54,330 --> 00:19:56,010 let's do something correct, like 50-- 433 00:19:56,010 --> 00:19:58,530 I see that x is 50. 434 00:19:58,530 --> 00:20:00,420 So line one is executed. 435 00:20:00,420 --> 00:20:01,890 We're trying to do the following. 436 00:20:01,890 --> 00:20:05,340 Line two is executed because the conversion happened successfully 437 00:20:05,340 --> 00:20:07,950 and the number 50 gets copied from right to left. 438 00:20:07,950 --> 00:20:10,030 The exception does not happen. 439 00:20:10,030 --> 00:20:11,670 So we ignore lines three and four. 440 00:20:11,670 --> 00:20:16,110 We jump immediately to line five and six, which prints out the result. 441 00:20:16,110 --> 00:20:18,810 By contrast, though-- let's do this one last time. 442 00:20:18,810 --> 00:20:23,160 Python of number.py-- let's type in cat or, again, any other word and hit Enter 443 00:20:23,160 --> 00:20:23,700 now. 444 00:20:23,700 --> 00:20:25,380 We don't see what x is. 445 00:20:25,380 --> 00:20:29,380 Rather, we see, quote unquote, "x is not an integer," 446 00:20:29,380 --> 00:20:33,030 which is what's being handled in my except clause. 447 00:20:33,030 --> 00:20:35,880 All right, let me pause here because that's a lot of new syntax, 448 00:20:35,880 --> 00:20:39,510 and see here if there's any questions on try, on except, 449 00:20:39,510 --> 00:20:42,870 on else, name error, or value error. 450 00:20:42,870 --> 00:20:45,792 AUDIENCE: Can you please repeat the try function? 451 00:20:45,792 --> 00:20:47,250 DAVID MALAN: Repeat the name error? 452 00:20:47,250 --> 00:20:48,870 What's the problem with the name error? 453 00:20:48,870 --> 00:20:49,200 AUDIENCE: Yes. 454 00:20:49,200 --> 00:20:49,500 Yes. 455 00:20:49,500 --> 00:20:50,208 DAVID MALAN: Yes. 456 00:20:50,208 --> 00:20:52,710 So let's just rewind a couple of lines here 457 00:20:52,710 --> 00:20:55,890 before I fix this problem by now getting rid of the else. 458 00:20:55,890 --> 00:21:00,360 A moment ago, we had code that looked like this, whereby 459 00:21:00,360 --> 00:21:03,780 I was getting a name error, Python of number.py, Enter, 460 00:21:03,780 --> 00:21:07,710 typing in cat, that looked like this, where name x is not defined. 461 00:21:07,710 --> 00:21:11,700 And the problem was on line six, according to this output in Python. 462 00:21:11,700 --> 00:21:13,798 Well, let's think about this now deductively. 463 00:21:13,798 --> 00:21:15,090 Let's try a different approach. 464 00:21:15,090 --> 00:21:18,660 On line six, I'm seeing an error that name x is not defined. 465 00:21:18,660 --> 00:21:22,150 OK, Python's already telling me x does not exist at that point. 466 00:21:22,150 --> 00:21:23,820 So how could that possibly be? 467 00:21:23,820 --> 00:21:26,340 Well, where should x be defined? 468 00:21:26,340 --> 00:21:29,940 Well, presumably, x is defined on line two, up here. 469 00:21:29,940 --> 00:21:31,440 So what could go wrong? 470 00:21:31,440 --> 00:21:35,210 Well, if the user has inputted something that doesn't look like a number, 471 00:21:35,210 --> 00:21:40,220 like the word cat, passing cat, the return value of input, 472 00:21:40,220 --> 00:21:45,810 as the argument to int to convert the word to an int makes no sense. 473 00:21:45,810 --> 00:21:49,550 You can't convert a cat, C-A-T, to an integer at all. 474 00:21:49,550 --> 00:21:55,370 So the int function is raising a value error at that point. 475 00:21:55,370 --> 00:21:58,770 And the error is being handled with this code here. 476 00:21:58,770 --> 00:22:02,150 But notice this line six is not indented. 477 00:22:02,150 --> 00:22:06,500 It's left aligned with the rest of my code, which means no matter what, 478 00:22:06,500 --> 00:22:08,240 line six is going to execute. 479 00:22:08,240 --> 00:22:12,020 It's going to execute whether I typed in 50 or I typed in cat. 480 00:22:12,020 --> 00:22:15,540 But if I typed in cat, again, x never gets a value. 481 00:22:15,540 --> 00:22:17,990 So it's not defined here on line six. 482 00:22:17,990 --> 00:22:21,080 So when I introduced, finally, the else statement, that 483 00:22:21,080 --> 00:22:23,700 makes sure that these things are mutually exclusive. 484 00:22:23,700 --> 00:22:29,990 I only execute the else if I tried and succeeded up above. 485 00:22:29,990 --> 00:22:35,390 Well, let me propose that we refine this just a little bit further as well 486 00:22:35,390 --> 00:22:39,380 and consider how we might improve this example a little bit more. 487 00:22:39,380 --> 00:22:45,950 It's a little unfriendly of me to be rejecting the user's input after they 488 00:22:45,950 --> 00:22:49,220 fail to provide an integer and just quitting the program, really, right? 489 00:22:49,220 --> 00:22:51,950 It'd be more user friendly if I just prompt 490 00:22:51,950 --> 00:22:54,350 or reprompt the user again and again. 491 00:22:54,350 --> 00:22:58,310 And in the chat, if you could, what's the feature of Python 492 00:22:58,310 --> 00:23:01,340 that you can use if you want to do something again and again 493 00:23:01,340 --> 00:23:04,970 and again until such time as the user cooperates and gives you 494 00:23:04,970 --> 00:23:07,370 what you're looking for, like a number? 495 00:23:07,370 --> 00:23:09,120 So yeah, loop, loop, loop. 496 00:23:09,120 --> 00:23:12,360 So a loop is something that happens again and again and again. 497 00:23:12,360 --> 00:23:15,920 And maybe we can use that same mechanism, a loop, in order 498 00:23:15,920 --> 00:23:17,300 to prompt the user for x. 499 00:23:17,300 --> 00:23:19,635 And if they don't give us a number, prompt them again. 500 00:23:19,635 --> 00:23:22,010 And if they don't, prompt them again and again and again. 501 00:23:22,010 --> 00:23:24,060 We don't need to just quit out of the program. 502 00:23:24,060 --> 00:23:26,120 So, quickly-- so let me propose this. 503 00:23:26,120 --> 00:23:30,590 Let me propose here that I improve this code by deliberately doing this. 504 00:23:30,590 --> 00:23:36,380 Let me induce a infinite loop at the very top of my code with while true. 505 00:23:36,380 --> 00:23:40,400 Recall that the wild keyword induces a loop, a cycle that behaves like this. 506 00:23:40,400 --> 00:23:42,920 And it asks a question, a Boolean expression 507 00:23:42,920 --> 00:23:45,420 that needs to evaluate either to true or false. 508 00:23:45,420 --> 00:23:47,300 Well, if I want this thing to loop forever, 509 00:23:47,300 --> 00:23:51,502 at least initially, we'll just say while true because true is true. 510 00:23:51,502 --> 00:23:53,210 So this has the effect of doing something 511 00:23:53,210 --> 00:23:56,600 no matter what forever unless we break out of it early. 512 00:23:56,600 --> 00:23:58,980 Now I'm going to go ahead and do this. 513 00:23:58,980 --> 00:24:02,420 I'm going to go ahead and move my try except code 514 00:24:02,420 --> 00:24:06,740 indented underneath this loop so that I'm trying to get an x. 515 00:24:06,740 --> 00:24:11,120 If I have a value error instead, I print out x is not an integer. 516 00:24:11,120 --> 00:24:15,230 But this time, what do I want to do if the user does 517 00:24:15,230 --> 00:24:18,680 try and succeed in giving me a number? 518 00:24:18,680 --> 00:24:20,100 Well, I can do this. 519 00:24:20,100 --> 00:24:22,400 I can just break out of my code here. 520 00:24:22,400 --> 00:24:25,160 And down here now, I can use that same line of code 521 00:24:25,160 --> 00:24:31,130 from before, an F-string that says x is, and then in curly braces, x again. 522 00:24:31,130 --> 00:24:32,910 So what's going on here? 523 00:24:32,910 --> 00:24:35,270 I think this code now, because I've added 524 00:24:35,270 --> 00:24:39,350 the loop, is going to have the effect of trying at least once, maybe 525 00:24:39,350 --> 00:24:44,360 a second time, maybe a third time maybe 500 times until the user finally gives 526 00:24:44,360 --> 00:24:46,610 me what I want, which is an integer. 527 00:24:46,610 --> 00:24:50,000 And once they do, once there's no value error happening, 528 00:24:50,000 --> 00:24:51,860 then I break out of the loop. 529 00:24:51,860 --> 00:24:54,350 And line nine executes as I would hope. 530 00:24:54,350 --> 00:24:56,540 So let me go ahead and try executing this version-- 531 00:24:56,540 --> 00:24:58,970 Python of number.py, Enter. 532 00:24:58,970 --> 00:24:59,990 What's x? 533 00:24:59,990 --> 00:25:02,090 Let me go ahead and type in the easy thing first-- 534 00:25:02,090 --> 00:25:03,210 50. 535 00:25:03,210 --> 00:25:03,710 X is 50. 536 00:25:03,710 --> 00:25:06,680 What just happened in terms of the control flow 537 00:25:06,680 --> 00:25:08,780 of this program, the flow of my logic? 538 00:25:08,780 --> 00:25:11,750 Well, I first found myself on line one inside of a loop. 539 00:25:11,750 --> 00:25:13,370 Hopefully, I'll get out of this loop. 540 00:25:13,370 --> 00:25:14,390 What did I then do? 541 00:25:14,390 --> 00:25:18,080 On lines two and three, I tried to get input from the user 542 00:25:18,080 --> 00:25:19,160 and convert it to an int. 543 00:25:19,160 --> 00:25:20,900 Well, I was a nice guy this time. 544 00:25:20,900 --> 00:25:23,390 And I typed in 50, which looks like and is a number. 545 00:25:23,390 --> 00:25:25,250 So the int function converted it just fine 546 00:25:25,250 --> 00:25:28,280 and stored it from right to left in x. 547 00:25:28,280 --> 00:25:29,390 Except value error? 548 00:25:29,390 --> 00:25:31,760 There is no value error because if I typed in a number, 549 00:25:31,760 --> 00:25:33,410 there's nothing exceptional happening. 550 00:25:33,410 --> 00:25:36,930 This is a boring, good execution of my program. 551 00:25:36,930 --> 00:25:38,120 So what happens? 552 00:25:38,120 --> 00:25:39,810 I break out of the loop. 553 00:25:39,810 --> 00:25:44,780 So, again, the else clause is associated with the try not with the except. 554 00:25:44,780 --> 00:25:47,990 And once I'm out of the loop, of course, I'm just printing out what x is. 555 00:25:47,990 --> 00:25:50,480 Well, let's try the other scenario that might happen. 556 00:25:50,480 --> 00:25:52,730 Python of number.py, Enter. 557 00:25:52,730 --> 00:25:53,390 What's x? 558 00:25:53,390 --> 00:25:55,400 Let's try cat or any other word. 559 00:25:55,400 --> 00:25:56,810 Enter. 560 00:25:56,810 --> 00:25:59,510 Ah, this is now a new feature. 561 00:25:59,510 --> 00:26:01,610 I'm being informed what I did wrong. 562 00:26:01,610 --> 00:26:02,790 X is not an integer. 563 00:26:02,790 --> 00:26:05,120 So I'm getting some useful user feedback. 564 00:26:05,120 --> 00:26:07,520 But notice, again, I'm prompted, what's x? 565 00:26:07,520 --> 00:26:09,860 Well, let me try typing in dog. 566 00:26:09,860 --> 00:26:11,040 X is not an integer. 567 00:26:11,040 --> 00:26:11,750 What's x? 568 00:26:11,750 --> 00:26:13,100 Let me try bird. 569 00:26:13,100 --> 00:26:14,210 Enter. 570 00:26:14,210 --> 00:26:15,330 X is not an integer. 571 00:26:15,330 --> 00:26:15,830 What's x? 572 00:26:15,830 --> 00:26:19,850 And suffice it to say, this will happen now forever if I'm in an infinite loop 573 00:26:19,850 --> 00:26:23,768 until I try and succeed, at which point I break out. 574 00:26:23,768 --> 00:26:24,560 So let's try again. 575 00:26:24,560 --> 00:26:25,480 50, Enter. 576 00:26:25,480 --> 00:26:26,980 Now I'm out of the loop. 577 00:26:26,980 --> 00:26:30,530 And I'm printing out what x actually is. 578 00:26:30,530 --> 00:26:33,970 All right, let me pause here and see if there are any questions. 579 00:26:33,970 --> 00:26:35,560 The logic is almost the same. 580 00:26:35,560 --> 00:26:38,080 But what is different now is I'm in a loop. 581 00:26:38,080 --> 00:26:40,870 And I'm using the keyword break in Python 582 00:26:40,870 --> 00:26:43,510 to deliberately break out of the loop when I'm 583 00:26:43,510 --> 00:26:46,540 ready to, once the user has cooperated. 584 00:26:46,540 --> 00:26:48,910 AUDIENCE: Do we really need to break? 585 00:26:48,910 --> 00:26:51,130 Can't we just print? 586 00:26:51,130 --> 00:26:54,235 Or what keeps us from just printing? 587 00:26:54,235 --> 00:26:55,360 DAVID MALAN: Good question. 588 00:26:55,360 --> 00:26:56,290 So let me try that. 589 00:26:56,290 --> 00:26:57,490 Couldn't I just print? 590 00:26:57,490 --> 00:26:59,240 Well, let's see what happens if I do that. 591 00:26:59,240 --> 00:27:02,710 Let me move this print line at the end into my loop 592 00:27:02,710 --> 00:27:04,380 here, thereby shortening the program. 593 00:27:04,380 --> 00:27:06,130 And, in general, that's been a good thing. 594 00:27:06,130 --> 00:27:08,410 Python of number.py, Enter. 595 00:27:08,410 --> 00:27:10,530 Let me go ahead and type in 50. 596 00:27:10,530 --> 00:27:11,410 OK, x is 50. 597 00:27:11,410 --> 00:27:13,105 What's x? 598 00:27:13,105 --> 00:27:14,395 OK, maybe it's 49. 599 00:27:14,395 --> 00:27:15,700 X is 49. 600 00:27:15,700 --> 00:27:17,320 OK, maybe 48. 601 00:27:17,320 --> 00:27:19,030 Unfortunately, I think-- you're laughing. 602 00:27:19,030 --> 00:27:19,530 You see it. 603 00:27:19,530 --> 00:27:22,115 I never break out of the loop, which maybe that's a feature. 604 00:27:22,115 --> 00:27:23,740 Maybe you want this to be your program. 605 00:27:23,740 --> 00:27:24,282 But I didn't. 606 00:27:24,282 --> 00:27:25,870 I'd eventually like this game to stop. 607 00:27:25,870 --> 00:27:28,150 So I need to break out in that way. 608 00:27:28,150 --> 00:27:29,890 But I can do it a little differently. 609 00:27:29,890 --> 00:27:33,200 And let me propose that we modify this a little bit. 610 00:27:33,200 --> 00:27:36,130 But, first, any other questions on this syntax here? 611 00:27:36,130 --> 00:27:41,302 Let me rewind to the prior version. 612 00:27:41,302 --> 00:27:46,870 AUDIENCE: Hi, can I use a break [INAUDIBLE] except and else? 613 00:27:46,870 --> 00:27:51,700 For example, in another print, may you use printing the else, 614 00:27:51,700 --> 00:27:55,760 you can use prints together with break or something like this? 615 00:27:55,760 --> 00:27:59,110 DAVID MALAN: So you can use break inside of loops to break out of loops. 616 00:27:59,110 --> 00:28:01,450 And you can use it inside of a conditional, 617 00:28:01,450 --> 00:28:03,610 like an if, an elif, or an else. 618 00:28:03,610 --> 00:28:06,940 You can do it inside of a try, except, else statement to. 619 00:28:06,940 --> 00:28:09,190 Any time you're in a loop that you want to break out 620 00:28:09,190 --> 00:28:11,110 of, you can use this keyword, break. 621 00:28:11,110 --> 00:28:13,120 I'm using it in the context of exceptions. 622 00:28:13,120 --> 00:28:14,538 But it's not restricted to that. 623 00:28:14,538 --> 00:28:15,580 And let me show you, too. 624 00:28:15,580 --> 00:28:17,205 It doesn't even have to be in the else. 625 00:28:17,205 --> 00:28:20,140 If I wanted to, I could actually do this. 626 00:28:20,140 --> 00:28:21,940 I could get rid of my else. 627 00:28:21,940 --> 00:28:26,170 And I could go back to line three, add another line that's indented, 628 00:28:26,170 --> 00:28:28,910 line four, and break out here. 629 00:28:28,910 --> 00:28:31,450 Now, why is this logically OK? 630 00:28:31,450 --> 00:28:34,610 Well, consider what I'm now trying to do. 631 00:28:34,610 --> 00:28:38,890 I'm trying to execute line three and converting the user's input to an int. 632 00:28:38,890 --> 00:28:42,910 And I'm trying to store the result from right to left in x. 633 00:28:42,910 --> 00:28:45,700 If something goes wrong, the code we've already seen 634 00:28:45,700 --> 00:28:48,670 is immediately going to jump to line five 635 00:28:48,670 --> 00:28:51,740 and then six to handle the exception. 636 00:28:51,740 --> 00:28:54,430 But if nothing goes wrong, my code presumably 637 00:28:54,430 --> 00:28:57,410 should just keep on executing line by line. 638 00:28:57,410 --> 00:29:00,170 So I could technically logically put the break here. 639 00:29:00,170 --> 00:29:02,290 And watch what happens when I run this version. 640 00:29:02,290 --> 00:29:06,520 Python of number.py, 50, Enter, it worked. 641 00:29:06,520 --> 00:29:08,050 I broke out of the loop. 642 00:29:08,050 --> 00:29:09,760 Now, which way is better? 643 00:29:09,760 --> 00:29:12,460 Honestly, I think it could go either way at this point. 644 00:29:12,460 --> 00:29:15,100 This program is so relatively short that even 645 00:29:15,100 --> 00:29:18,760 though I'm trying to do two things now, one of which, the break, 646 00:29:18,760 --> 00:29:19,870 is not going to fail. 647 00:29:19,870 --> 00:29:21,273 You either break or you don't. 648 00:29:21,273 --> 00:29:24,190 There's no piece of data from the user that's going to influence that. 649 00:29:24,190 --> 00:29:27,310 We don't strictly need to have those two lines of code there. 650 00:29:27,310 --> 00:29:28,378 But it's only two lines. 651 00:29:28,378 --> 00:29:29,170 So I think it's OK. 652 00:29:29,170 --> 00:29:32,128 And if you recall our discussion in the past, not just of correctness-- 653 00:29:32,128 --> 00:29:34,720 does the code work as it should?-- but design, 654 00:29:34,720 --> 00:29:36,400 I think you could argue it either way. 655 00:29:36,400 --> 00:29:38,860 If you prefer the readability of this and the fact 656 00:29:38,860 --> 00:29:41,050 that you don't have an else, that's fine. 657 00:29:41,050 --> 00:29:43,420 If, though, you prefer to minimize just how 658 00:29:43,420 --> 00:29:47,230 many lines of code you're trying to execute in case something goes wrong, 659 00:29:47,230 --> 00:29:50,050 the else is a reasonable approach too. 660 00:29:50,050 --> 00:29:53,050 Well, allow me to propose, too, now that we refine this further. 661 00:29:53,050 --> 00:29:56,290 I think we're at the point where it's pretty darn correct. 662 00:29:56,290 --> 00:30:00,250 But suppose now that I find myself today and tomorrow 663 00:30:00,250 --> 00:30:02,890 trying to get numbers from the user quite a bit. 664 00:30:02,890 --> 00:30:06,100 It would be nice, as we've seen, to maybe just invent my own function, 665 00:30:06,100 --> 00:30:10,160 get int to get an integer from the user both today and tomorrow and beyond. 666 00:30:10,160 --> 00:30:12,910 And, heck, maybe I can even share that function with other people. 667 00:30:12,910 --> 00:30:15,950 If they want to write programs, they get integers from users. 668 00:30:15,950 --> 00:30:17,767 So how might I go about doing this? 669 00:30:17,767 --> 00:30:19,850 Well, let me go ahead and propose that we do this. 670 00:30:19,850 --> 00:30:22,720 Let me get rid of the print line but keep most of my loop here. 671 00:30:22,720 --> 00:30:27,427 Let me define a function called get int that takes no arguments for now. 672 00:30:27,427 --> 00:30:30,010 And I'm going to go ahead and indent all of the code I already 673 00:30:30,010 --> 00:30:31,780 wrote underneath get int. 674 00:30:31,780 --> 00:30:37,390 So now I have a function called get int that tries to do the following. 675 00:30:37,390 --> 00:30:39,177 Try to get in it from the user. 676 00:30:39,177 --> 00:30:41,260 If something goes wrong and there's a value error, 677 00:30:41,260 --> 00:30:43,360 yell at them with x is not an integer. 678 00:30:43,360 --> 00:30:45,130 Else, break. 679 00:30:45,130 --> 00:30:47,890 But it's not just breaking that I want to do here. 680 00:30:47,890 --> 00:30:51,850 Now that I'm in a function, recall our discussion of return values. 681 00:30:51,850 --> 00:30:54,858 If you're inventing your own function whose purpose in life 682 00:30:54,858 --> 00:30:57,400 isn't just a print something on the screen like a side effect 683 00:30:57,400 --> 00:31:01,930 but is to hand back a value, to hand you back a value, 684 00:31:01,930 --> 00:31:05,180 like on that same post-it note from our discussion of functions, 685 00:31:05,180 --> 00:31:07,570 well, you need to return x explicitly. 686 00:31:07,570 --> 00:31:09,225 How do I now use this function? 687 00:31:09,225 --> 00:31:11,350 Well, as soon as we start making our own functions, 688 00:31:11,350 --> 00:31:14,590 it tends to be convenient to define our own main function as well. 689 00:31:14,590 --> 00:31:16,280 That's the main part of our program. 690 00:31:16,280 --> 00:31:17,697 And I'm going to keep this simple. 691 00:31:17,697 --> 00:31:20,380 I'm now going to say, x equals get int. 692 00:31:20,380 --> 00:31:23,500 And then on the next line, I'm going to do that print from before, quote 693 00:31:23,500 --> 00:31:25,870 unquote, "x is"-- in curly braces-- 694 00:31:25,870 --> 00:31:26,500 "x." 695 00:31:26,500 --> 00:31:28,960 And at the very bottom of my program recall, 696 00:31:28,960 --> 00:31:31,240 I'm going to call main, so that no matter what, 697 00:31:31,240 --> 00:31:34,480 I'm invoking my main function after everything's been defined. 698 00:31:34,480 --> 00:31:35,840 Well, let's see how this works. 699 00:31:35,840 --> 00:31:39,710 Let me go ahead and run Python of number.py. 700 00:31:39,710 --> 00:31:40,310 Enter. 701 00:31:40,310 --> 00:31:41,380 Let's type in 50. 702 00:31:41,380 --> 00:31:43,520 And it seems to work as before. 703 00:31:43,520 --> 00:31:47,330 Let's go ahead and run it again, typing in cat, C-A-T, this time. 704 00:31:47,330 --> 00:31:48,380 X is not an integer. 705 00:31:48,380 --> 00:31:49,520 And I'm being prompted. 706 00:31:49,520 --> 00:31:51,320 Dog, and I'm being prompted. 707 00:31:51,320 --> 00:31:52,850 Bird, and I'm being prompted. 708 00:31:52,850 --> 00:31:53,770 Fine, fine, fine. 709 00:31:53,770 --> 00:31:54,270 50. 710 00:31:54,270 --> 00:31:55,640 That's an int. 711 00:31:55,640 --> 00:31:57,200 And so it is printed. 712 00:31:57,200 --> 00:32:00,690 So what's worth noting here-- well, I'm manifesting a couple of good properties 713 00:32:00,690 --> 00:32:01,190 here. 714 00:32:01,190 --> 00:32:05,510 One, I've kind of abstracted away this notion of getting an integer. 715 00:32:05,510 --> 00:32:07,732 And even though I just artificially hit Enter 716 00:32:07,732 --> 00:32:10,190 a whole bunch of times just to hide that function for now-- 717 00:32:10,190 --> 00:32:13,190 it needs to be there, but we don't need to see it at this point-- notice 718 00:32:13,190 --> 00:32:15,350 that now this entire program really boils down 719 00:32:15,350 --> 00:32:17,480 to just these three lines of code now. 720 00:32:17,480 --> 00:32:18,110 Why? 721 00:32:18,110 --> 00:32:22,040 Because I've abstracted away that whole process of getting an int from the user 722 00:32:22,040 --> 00:32:25,250 into this new function of my own called get int. 723 00:32:25,250 --> 00:32:26,850 But can I improve upon this? 724 00:32:26,850 --> 00:32:29,660 Well, let me go and undo all of those blank lines 725 00:32:29,660 --> 00:32:32,330 and pull this up just so we can see more on the screen at once. 726 00:32:32,330 --> 00:32:34,910 Can I tighten up my implementation of get int? 727 00:32:34,910 --> 00:32:35,840 It is correct. 728 00:32:35,840 --> 00:32:37,220 I claim this is correct. 729 00:32:37,220 --> 00:32:38,330 It's handling errors. 730 00:32:38,330 --> 00:32:39,440 And it's returning x. 731 00:32:39,440 --> 00:32:43,170 But I don't, strictly speaking, need to write the code as long. 732 00:32:43,170 --> 00:32:44,790 What else could I do? 733 00:32:44,790 --> 00:32:48,710 Well, let me propose that if all you're doing on this line 13 is breaking 734 00:32:48,710 --> 00:32:51,530 and then immediately after that, per the indentation, 735 00:32:51,530 --> 00:32:56,450 you're executing return x on line 14, why are you wasting everyone's time? 736 00:32:56,450 --> 00:33:00,440 Once you know you're ready to return the value, you could just return x. 737 00:33:00,440 --> 00:33:03,900 And so in my else, I could break out and return a value. 738 00:33:03,900 --> 00:33:08,780 So here, too, return is used to return values from functions. 739 00:33:08,780 --> 00:33:11,780 Break is used to break out of loops. 740 00:33:11,780 --> 00:33:15,710 But it turns out that return is sort of stronger than break. 741 00:33:15,710 --> 00:33:17,960 It will not only break you out of a loop. 742 00:33:17,960 --> 00:33:20,510 It will also return a value for you. 743 00:33:20,510 --> 00:33:23,870 So it's doing two things for once, if you will. 744 00:33:23,870 --> 00:33:28,100 But can I make this even more compact? 745 00:33:28,100 --> 00:33:32,690 If my goal is to just tighten the code up, even though it's already correct, 746 00:33:32,690 --> 00:33:34,910 can anyone think of a further refinement, 747 00:33:34,910 --> 00:33:37,730 whether you've programmed in Python before or not? 748 00:33:37,730 --> 00:33:41,330 Can I shorten this implementation further just a little bit, 749 00:33:41,330 --> 00:33:43,610 if only to decrease the probability that I've 750 00:33:43,610 --> 00:33:45,980 made a mistake by having fewer lines and just 751 00:33:45,980 --> 00:33:49,100 make it a little easier to read because it's shorter? 752 00:33:49,100 --> 00:33:53,077 Any suggestions for tightening up my implementation of get int? 753 00:33:53,077 --> 00:33:55,160 AUDIENCE: You can just return the value on the try 754 00:33:55,160 --> 00:33:59,720 function, when you're trying. 755 00:33:59,720 --> 00:34:02,180 You take the input x and then return x. 756 00:34:02,180 --> 00:34:02,930 DAVID MALAN: Good. 757 00:34:02,930 --> 00:34:05,480 We can just return x a little higher up. 758 00:34:05,480 --> 00:34:07,030 And let me correct folks as we go. 759 00:34:07,030 --> 00:34:08,030 It's not a try function. 760 00:34:08,030 --> 00:34:09,739 It would be a try statement, technically. 761 00:34:09,739 --> 00:34:12,350 A function typically has a parentheses and another one. 762 00:34:12,350 --> 00:34:14,030 In this case, it's just a statement. 763 00:34:14,030 --> 00:34:15,690 But we can do exactly that. 764 00:34:15,690 --> 00:34:17,300 I don't technically need the else. 765 00:34:17,300 --> 00:34:19,340 If I really want, I could do this. 766 00:34:19,340 --> 00:34:22,520 Right after line nine, I could return x here. 767 00:34:22,520 --> 00:34:27,530 Or recall our discussion of defining variables unnecessarily sometimes. 768 00:34:27,530 --> 00:34:29,780 Why define a variable here if you're immediately going 769 00:34:29,780 --> 00:34:31,520 to use it here and then never again? 770 00:34:31,520 --> 00:34:33,860 So we could avoid a new line here. 771 00:34:33,860 --> 00:34:37,340 And I could avoid even defining x explicitly. 772 00:34:37,340 --> 00:34:39,080 I could just say something like this. 773 00:34:39,080 --> 00:34:42,889 I could return int, input, quote unquote, "what's x?" 774 00:34:42,889 --> 00:34:44,270 I can do it all at once. 775 00:34:44,270 --> 00:34:46,620 Now, which is better? 776 00:34:46,620 --> 00:34:47,580 I don't know. 777 00:34:47,580 --> 00:34:50,239 I mean, again, this is where reasonable people might disagree. 778 00:34:50,239 --> 00:34:53,210 I'd argue that, on the one hand, we're tightening up the code. 779 00:34:53,210 --> 00:34:54,650 We're using fewer lines. 780 00:34:54,650 --> 00:34:57,890 It's easier to read, lower probability that I've made a mistake. 781 00:34:57,890 --> 00:35:01,640 On the other hand, it's a little more complicated to understand, perhaps. 782 00:35:01,640 --> 00:35:04,070 It's a little less obvious where I'm returning from. 783 00:35:04,070 --> 00:35:06,050 So I think arguments can be made either way. 784 00:35:06,050 --> 00:35:09,530 At the end of the day, what's important is that you've done this consciously. 785 00:35:09,530 --> 00:35:12,180 You've made a decision to do it this way or this way. 786 00:35:12,180 --> 00:35:16,130 And you can justify it in your mind-- not that your answer is, eh, it worked, 787 00:35:16,130 --> 00:35:17,210 so I left it alone. 788 00:35:17,210 --> 00:35:18,080 Have a good reason. 789 00:35:18,080 --> 00:35:19,205 Come up with a good reason. 790 00:35:19,205 --> 00:35:22,010 And that will come with experience and practice. 791 00:35:22,010 --> 00:35:25,670 Well, let me propose to you that we make one other refinement here. 792 00:35:25,670 --> 00:35:28,910 Suppose that you're finding your programs to be a little noisy. 793 00:35:28,910 --> 00:35:31,370 And it's a little obnoxious that you keep telling the user, 794 00:35:31,370 --> 00:35:32,390 x is not an integer. 795 00:35:32,390 --> 00:35:33,410 X is not an integer. 796 00:35:33,410 --> 00:35:34,460 X is not an integer. 797 00:35:34,460 --> 00:35:38,780 What if you want to make things a little gentler and just prompt 798 00:35:38,780 --> 00:35:41,810 the user again with the same words, what's x? 799 00:35:41,810 --> 00:35:42,500 What is x? 800 00:35:42,500 --> 00:35:43,280 What's x? 801 00:35:43,280 --> 00:35:44,330 Again and again. 802 00:35:44,330 --> 00:35:45,930 Well, you can do that as well. 803 00:35:45,930 --> 00:35:49,970 And it turns out that if you want to handle an exception in Python 804 00:35:49,970 --> 00:35:54,590 but you want to pass on doing anything with it-- so you want to catch it, 805 00:35:54,590 --> 00:35:56,510 but you essentially want to ignore it. 806 00:35:56,510 --> 00:35:57,920 You don't want to print anything. 807 00:35:57,920 --> 00:35:59,720 You don't want to quit the program. 808 00:35:59,720 --> 00:36:02,330 You just want to silently ignore it, like 809 00:36:02,330 --> 00:36:05,460 if you're talking in a room full of people and it's your turn to talk 810 00:36:05,460 --> 00:36:07,070 and you're just like, pass. 811 00:36:07,070 --> 00:36:08,390 They're still calling on you. 812 00:36:08,390 --> 00:36:10,610 But you're not doing or saying anything more. 813 00:36:10,610 --> 00:36:13,250 Well, we can add this keyword to our code here. 814 00:36:13,250 --> 00:36:15,230 Let me go back to my program here. 815 00:36:15,230 --> 00:36:19,070 And instead of printing out again and again, x is not an integer, 816 00:36:19,070 --> 00:36:20,330 I could just do this. 817 00:36:20,330 --> 00:36:23,300 I could pass on handling the error further. 818 00:36:23,300 --> 00:36:24,500 I'm still catching it. 819 00:36:24,500 --> 00:36:28,040 So the user is not going to see a scary message even mentioning value error. 820 00:36:28,040 --> 00:36:29,390 My code is catching it. 821 00:36:29,390 --> 00:36:32,220 But I'm passing on saying anything about it. 822 00:36:32,220 --> 00:36:33,470 I'm going to stay in the loop. 823 00:36:33,470 --> 00:36:36,512 I'm going to stay in the loop and keep prompting and reprompting the user 824 00:36:36,512 --> 00:36:38,790 so now the effect looks a little something like this. 825 00:36:38,790 --> 00:36:40,470 Python of number.py. 826 00:36:40,470 --> 00:36:42,180 Let's type in cat. 827 00:36:42,180 --> 00:36:43,140 What's x again? 828 00:36:43,140 --> 00:36:44,310 Let's type in dog. 829 00:36:44,310 --> 00:36:45,430 What's x again? 830 00:36:45,430 --> 00:36:46,230 Type in bird. 831 00:36:46,230 --> 00:36:49,290 So it's just a little, maybe, more user friendly and that you're just 832 00:36:49,290 --> 00:36:50,820 reminding the user what you want. 833 00:36:50,820 --> 00:36:51,810 Maybe it's worse. 834 00:36:51,810 --> 00:36:54,630 Maybe it would be helpful to tell the user why 835 00:36:54,630 --> 00:36:56,500 you're prompting them again and again. 836 00:36:56,500 --> 00:36:57,250 It's not obvious. 837 00:36:57,250 --> 00:36:58,540 So it could go both ways. 838 00:36:58,540 --> 00:37:02,400 But, again, it's just another mechanism, now, for handling these errors. 839 00:37:02,400 --> 00:37:05,340 We use the except keyword to catch a specific error. 840 00:37:05,340 --> 00:37:07,620 But we don't have to handle it more than that. 841 00:37:07,620 --> 00:37:10,440 We can just pass on doing something further. 842 00:37:10,440 --> 00:37:15,480 Let me pause here and see if there's any questions now on try, accept, else, 843 00:37:15,480 --> 00:37:17,522 or pass? 844 00:37:17,522 --> 00:37:18,380 AUDIENCE: OK, yeah. 845 00:37:18,380 --> 00:37:18,880 No. 846 00:37:18,880 --> 00:37:22,220 I was just kind of curious, I guess, about the idea 847 00:37:22,220 --> 00:37:27,470 of when you were inventing with the get int function, for example. 848 00:37:27,470 --> 00:37:29,660 Because I'm noticing, obviously, going through it 849 00:37:29,660 --> 00:37:33,990 with the whole logic and breakdown of the entire function, while true, 850 00:37:33,990 --> 00:37:34,490 do this. 851 00:37:34,490 --> 00:37:37,198 But I'm just kind of curious in elaborating with the indentations 852 00:37:37,198 --> 00:37:38,660 for the code more. 853 00:37:38,660 --> 00:37:39,410 DAVID MALAN: Yeah. 854 00:37:39,410 --> 00:37:41,960 So the invitation is deliberate logically. 855 00:37:41,960 --> 00:37:45,500 Some languages don't require as rigorous indentation. 856 00:37:45,500 --> 00:37:47,780 You can use curly braces or other symbology 857 00:37:47,780 --> 00:37:49,940 to make clear what is associated with what. 858 00:37:49,940 --> 00:37:54,860 In general, any time you indent something in Python on this line-- 859 00:37:54,860 --> 00:37:58,250 rather, anytime you write a code a line of code in Python that's here 860 00:37:58,250 --> 00:38:00,950 and the lines below it are somehow indented, 861 00:38:00,950 --> 00:38:04,700 that means that those lines are somehow associated with that first line. 862 00:38:04,700 --> 00:38:07,370 And, presumably, those indented lines should only 863 00:38:07,370 --> 00:38:13,040 be executed if the first line told the computer to do so. 864 00:38:13,040 --> 00:38:14,900 So, concretely, what does this mean? 865 00:38:14,900 --> 00:38:17,660 On line six here, we're defining a function called 866 00:38:17,660 --> 00:38:20,660 get in that takes no arguments, colon. 867 00:38:20,660 --> 00:38:24,080 Everything that's indented by at least four spaces 868 00:38:24,080 --> 00:38:26,160 hereafter is part of that function. 869 00:38:26,160 --> 00:38:26,660 Why? 870 00:38:26,660 --> 00:38:29,450 That's just the design of the Python language. 871 00:38:29,450 --> 00:38:33,230 Frankly, I think the designers got tired of seeing really ugly code in languages 872 00:38:33,230 --> 00:38:40,310 like C and C++ and Java that don't necessarily enforce indentation to this 873 00:38:40,310 --> 00:38:40,980 extent. 874 00:38:40,980 --> 00:38:42,770 So now it's baked into the language. 875 00:38:42,770 --> 00:38:44,390 And my chronology might be a little off there. 876 00:38:44,390 --> 00:38:47,057 But there's been many languages that are looser than Python when 877 00:38:47,057 --> 00:38:48,980 it comes to indentation. 878 00:38:48,980 --> 00:38:51,770 The indentation is meaningful on line seven too. 879 00:38:51,770 --> 00:38:55,100 Notice that because the while true is indented by four spaces. 880 00:38:55,100 --> 00:38:57,270 That just means it's part of the get int function. 881 00:38:57,270 --> 00:39:01,400 But notice below the while true statement, there is eight, there's 12, 882 00:39:01,400 --> 00:39:03,435 there's eight, there's 12 spaces here. 883 00:39:03,435 --> 00:39:05,060 And I'm just quickly counting the dots. 884 00:39:05,060 --> 00:39:07,550 That means that all of the lines I've just highlighted 885 00:39:07,550 --> 00:39:09,590 are inside of that while loop. 886 00:39:09,590 --> 00:39:13,430 While true means to execute lines eight through 11, potentially, 887 00:39:13,430 --> 00:39:14,630 again and again and again. 888 00:39:14,630 --> 00:39:20,330 And now, lastly, on line eight, because we have try and indented below 889 00:39:20,330 --> 00:39:23,630 it is line nine, that just means that what you should try 890 00:39:23,630 --> 00:39:24,950 is what's on line nine. 891 00:39:24,950 --> 00:39:29,030 And similarly, on line 10, below it, we have indented line 11. 892 00:39:29,030 --> 00:39:33,840 You should only pass when there is an exception of a value error. 893 00:39:33,840 --> 00:39:37,043 So the indentation just means what is associated with what. 894 00:39:37,043 --> 00:39:38,960 And once you get comfortable with that, you'll 895 00:39:38,960 --> 00:39:43,670 see that the indentation alone helps explain the logic of your program. 896 00:39:43,670 --> 00:39:47,630 And it has a wonderful side effect that for yourself the next morning, 897 00:39:47,630 --> 00:39:51,080 for your colleagues, your family, your friends, your teachers, your code 898 00:39:51,080 --> 00:39:55,640 is much more readable as a result. It's not one big mess of a blob of text. 899 00:39:55,640 --> 00:39:59,780 Other questions now on try, except, else, or pass? 900 00:39:59,780 --> 00:40:01,460 AUDIENCE: Yeah, thanks. 901 00:40:01,460 --> 00:40:02,870 Two question. 902 00:40:02,870 --> 00:40:08,060 Question one-- once you say pass, can the caller 903 00:40:08,060 --> 00:40:14,420 still learn anything about this era through a system variable or whatever? 904 00:40:14,420 --> 00:40:19,410 And question two-- problem set zero referenced some string methods, 905 00:40:19,410 --> 00:40:21,680 including is numeric-- 906 00:40:21,680 --> 00:40:27,165 is it any different to [INAUDIBLE]? 907 00:40:27,165 --> 00:40:28,290 DAVID MALAN: Good question. 908 00:40:28,290 --> 00:40:30,860 So on the first question, if I'm handling the error in this way, 909 00:40:30,860 --> 00:40:32,943 the caller is not going to know anything about it. 910 00:40:32,943 --> 00:40:37,250 That's the point of my handling it, so that main or other callers don't know 911 00:40:37,250 --> 00:40:38,960 that anything technically went wrong. 912 00:40:38,960 --> 00:40:41,960 On the second question, is numeric is another function 913 00:40:41,960 --> 00:40:44,600 that you can call that can look at a string and determine 914 00:40:44,600 --> 00:40:46,340 is this, in fact, a number. 915 00:40:46,340 --> 00:40:48,650 I could use a mechanism like that. 916 00:40:48,650 --> 00:40:50,180 I could use a conditional. 917 00:40:50,180 --> 00:40:54,020 If this looks like a number, then pass it to the int function. 918 00:40:54,020 --> 00:40:56,030 And go ahead and convert it to an integer. 919 00:40:56,030 --> 00:40:57,410 That's totally fine. 920 00:40:57,410 --> 00:41:02,150 I would generally say that the Pythonic way of doing things is often, 921 00:41:02,150 --> 00:41:05,630 for better or for worse, to try things, hope they work. 922 00:41:05,630 --> 00:41:08,160 But if they don't, handle the exception. 923 00:41:08,160 --> 00:41:13,700 So other languages are more in favor of checking if, if, if, if, elif, else, 924 00:41:13,700 --> 00:41:15,080 and all of these conditionals. 925 00:41:15,080 --> 00:41:19,460 Python tends to be a little more of the mindset, eh, try it. 926 00:41:19,460 --> 00:41:21,510 But just make sure you're handling the error. 927 00:41:21,510 --> 00:41:23,438 So this would be the Pythonic way of doing it. 928 00:41:23,438 --> 00:41:26,480 Your way, though-- checking with the conditional, is it a number first?-- 929 00:41:26,480 --> 00:41:29,940 is totally reasonable too, if you want to go that way. 930 00:41:29,940 --> 00:41:32,000 Well, let me propose some final refinements 931 00:41:32,000 --> 00:41:34,970 to this program that really just kind of tighten things up, 932 00:41:34,970 --> 00:41:39,170 one additional step to improve the implementation of this 933 00:41:39,170 --> 00:41:40,220 get int function. 934 00:41:40,220 --> 00:41:44,870 Let me propose that we not hard code, so to speak-- that is type manually x 935 00:41:44,870 --> 00:41:45,900 all over the place. 936 00:41:45,900 --> 00:41:49,130 Let's make this function, get int, a little more reusable. 937 00:41:49,130 --> 00:41:53,870 Right now, notice that I'm just kind of using the honor system that, well, main 938 00:41:53,870 --> 00:41:55,940 is defining a variable called x. 939 00:41:55,940 --> 00:41:59,960 And get int is asking for a variable called x. 940 00:41:59,960 --> 00:42:02,720 But it would be nice if the caller, main, 941 00:42:02,720 --> 00:42:07,140 doesn't have to know what the call-ee is naming its variables and vise versa. 942 00:42:07,140 --> 00:42:09,620 So caller-- to call a function means to use it. 943 00:42:09,620 --> 00:42:11,750 The caller is the function that's using it. 944 00:42:11,750 --> 00:42:14,420 The call-ee is just the function being called. 945 00:42:14,420 --> 00:42:18,920 It would be nice if I'm not just hoping that x is the same in both places. 946 00:42:18,920 --> 00:42:20,530 So let me propose this. 947 00:42:20,530 --> 00:42:27,070 Let me propose that we actually add a parameter to get int, like this. 948 00:42:27,070 --> 00:42:28,330 What's x? 949 00:42:28,330 --> 00:42:31,540 That is to say, if main wants to use the get int function, 950 00:42:31,540 --> 00:42:35,110 well, then main should probably tell the get int function what 951 00:42:35,110 --> 00:42:36,310 prompt to show the user. 952 00:42:36,310 --> 00:42:40,090 Just like the input function, recall, that comes with Python, it's up to you 953 00:42:40,090 --> 00:42:45,320 to pass in a prompt that the user then sees when the human is asked for input. 954 00:42:45,320 --> 00:42:47,230 So how do I make this work here? 955 00:42:47,230 --> 00:42:49,390 I can go down to my definition of get int. 956 00:42:49,390 --> 00:42:53,080 And I can say, all right, get int is going to take a parameter now, 957 00:42:53,080 --> 00:42:53,770 called prompt. 958 00:42:53,770 --> 00:42:55,103 I could call it anything I want. 959 00:42:55,103 --> 00:42:57,550 But prompt in English is pretty self-explanatory. 960 00:42:57,550 --> 00:42:59,950 It means the message the user will see. 961 00:42:59,950 --> 00:43:02,800 And now, down here, when I actually use input, 962 00:43:02,800 --> 00:43:05,380 I don't have to presumptuously say, what's x? 963 00:43:05,380 --> 00:43:08,110 Because what if the program, the caller, wants 964 00:43:08,110 --> 00:43:10,900 to ask for y or z or some other variable? 965 00:43:10,900 --> 00:43:15,800 I can just pass to input whatever prompt the caller has provided. 966 00:43:15,800 --> 00:43:18,280 So now I'm making more reusable code. 967 00:43:18,280 --> 00:43:20,030 It still works just the same. 968 00:43:20,030 --> 00:43:22,120 I haven't changed the functionality, per se. 969 00:43:22,120 --> 00:43:24,490 But now it's a little more dynamic because now 970 00:43:24,490 --> 00:43:28,690 get int doesn't have to know or care what variable's being asked for, 971 00:43:28,690 --> 00:43:29,890 what's being asked for. 972 00:43:29,890 --> 00:43:33,410 It just needs to know what prompt it should show to the user. 973 00:43:33,410 --> 00:43:37,900 So if I now run this program down here, again, prompt number.py, Enter, 974 00:43:37,900 --> 00:43:38,620 what's x? 975 00:43:38,620 --> 00:43:40,480 50 still seems to work. 976 00:43:40,480 --> 00:43:41,300 Let's run it again. 977 00:43:41,300 --> 00:43:42,220 Let's type in cat. 978 00:43:42,220 --> 00:43:43,670 It still seems to work. 979 00:43:43,670 --> 00:43:46,210 And if I type in cat, dog, bird, or anything else, 980 00:43:46,210 --> 00:43:49,390 it will keep prompting me with that same prompt, making this code, 981 00:43:49,390 --> 00:43:51,730 therefore, all the more usable. 982 00:43:51,730 --> 00:43:55,150 Now it turns out, too, you can even raise exceptions yourself 983 00:43:55,150 --> 00:43:57,160 using Python's raise keyword. 984 00:43:57,160 --> 00:43:59,330 But more on that another time. 985 00:43:59,330 --> 00:44:01,960 So in the coming days, the coming weeks, the coming months, 986 00:44:01,960 --> 00:44:05,560 as you write more code in Python, you'll see that errors are inevitable. 987 00:44:05,560 --> 00:44:07,510 Sometimes they're syntax errors, which you've 988 00:44:07,510 --> 00:44:10,460 got to just fix if you even want to run your program at all. 989 00:44:10,460 --> 00:44:12,490 But they could be name errors-- for instance, 990 00:44:12,490 --> 00:44:15,880 variables that you meant to define but somehow didn't-- value errors, 991 00:44:15,880 --> 00:44:19,090 where maybe the user didn't cooperate and provided you with something that 992 00:44:19,090 --> 00:44:23,980 you weren't expecting, or a whole list of other possible errors or exceptions. 993 00:44:23,980 --> 00:44:26,800 But now, hopefully, you know how you can handle these errors 994 00:44:26,800 --> 00:44:29,080 and respond to them in any way you like. 995 00:44:29,080 --> 00:44:31,000 This, then, was our look at exceptions. 996 00:44:31,000 --> 00:44:33,720 And we'll see you next time. 997 00:44:33,720 --> 00:44:35,000