See all freeCodeCamp.org transcripts on Youtube

youtube thumbnail

Harvard CS50’s Introduction to Programming with Python – Full University Course

15 hours 57 minutes 47 seconds

🇬🇧 English

S1

Speaker 1

04:00:00

About 1 line at a time. And while you're on that line, the printer or the typewriter prints from left to right. And that's kind of the mental model to have with your black and white terminal window. All of the output for every example thus far starts at the top and goes down to the bottom, from top to bottom, left to right.

S1

Speaker 1

04:00:17

So we have to generate our output, our square, in that same way. So let me propose that we do this. Let me propose that we know we need to iterate this many times, 3, or more generally, size. So let me do this.

S1

Speaker 1

04:00:29

For I in the range of size, What do I need to do 3 times? Well, I want to print out what? 123 rows of bricks. But within each row of bricks, what do I want to print?

S1

Speaker 1

04:00:44

123 bricks specifically. So if we go back to our diagram here, and I stipulate that it's indeed meant to be a 3 by 3 square, 3 wide and 3 tall, what do I want to do to print the first row? I want to print brick, brick, brick, brick, brick. What do I want to print on the second row?

S1

Speaker 1

04:01:05

Brick, brick, brick. And the third row, brick, brick, brick. So I'm doing 3 things 3 times. There's a lot of printing that must happen.

S1

Speaker 1

04:01:13

So let me go back to my code here. And let me propose now that we think of this outer loop that I've just started as representing each of our rows. For I in range of size is going to ensure, no matter what I do next, that I can print out 1, 2, 3 rows, or more generally, size, where size could be 3, but it could be smaller or larger. What do I want to do on each of the rows?

S1

Speaker 1

04:01:40

Well, just like an old school typewriter or printer, on each row, I want to print out brick, brick, brick, brick, brick, brick, brick, brick, brick. Well, that sounds like a cycle, some kind of loop. So maybe I can have inside of 1 loop another loop. I don't want to use I again because I don't want to use the same variable and mess up my counting.

S1

Speaker 1

04:02:00

So I'm going to, by convention, use j, very common to use I and then j, maybe k. But after that, you shouldn't keep nesting inside of each other. Let me go ahead and say for j in range of size 2, because it's a square. And then each of these rows, let me print out a single hash, but no new line.

S1

Speaker 1

04:02:18

But after each row, let me print only a new line. So there's a lot going on here, especially if you've never touched Python, let alone loops. But Notice what I've done here, too. And I'll add some comments for clarity.

S1

Speaker 1

04:02:34

For each row in square, for each brick in row, print brick. And here is where comments, and more generally pseudocode, can really help explain to yourself and to others what your lines of code are doing. On line 8, I'm iterating from I equals 0 on up to psi, so 0, 1, 2. On line 11, I'm doing the exact same thing, but using j from 0, 1, 2.

S1

Speaker 1

04:03:04

But that's good, because I represent now each of my rows. And while I'm on each of those rows, inside of this outer loop, I'm going to do brick, brick, brick, 1, 2, 3, 1, 2, 3, 1, 2, 3. But I don't want my cursor to keep moving to the next line while I'm on a row, so I'm just overriding that line ending. But let me ask a question of the group now.

S1

Speaker 1

04:03:26

Why on line 16 do I have a print here all by itself? Why do I have a print all by itself? Notice that it's below the inner loop, but inside of the outer loop, so to speak. What is that loop on line 16 doing, ultimately?

S2

Speaker 2

04:03:49

Every time you finish a line, you have to add a new line at the end of it. So print prints a new line.

S1

Speaker 1

04:04:00

Perfect. I don't want a new line after every brick. I only want to do that at the end of the row. And that's why my comments now are perhaps enlightening.

S1

Speaker 1

04:04:08

Notice that this loop here is just iterating for each brick in the row. Once I'm done with that inner loop, so to speak, once I'm done with these highlighted lines here, to Evelyn's point, I need to print out 1 blank new line. And we've not done this before, but when you call print with no arguments, all you get is that automatic line ending, the backslash n, where the cursor moves to the next line. So if I now go back to my terminal window and run Mario.py, I think I should get a 3 by 3 square.

S1

Speaker 1

04:04:40

And it doesn't quite look like a square on my screen, because these hashes are a little taller than they are wide. But it is, in fact, 3 by 3. But let me propose, as we've always done here, how we might tighten up this code further. Just for clarity's sake, let me get rid of my comments for a moment, just so we can see how many lines of code we have total.

S1

Speaker 1

04:04:59

And let me propose that we maybe do this. Let me propose that, you know what, this inner loop, especially if you're having trouble wrapping your mind around 1 loop inside of another loop, you don't strictly need it. What if we do this trick again? What if we print out inside of the outer and only loop each of those hashes times the number of times we want them.

S1

Speaker 1

04:05:21

We draw inspiration from an earlier approach, and we run Python now of Mario.py, same result. But now print square is really nice and compact. It has 1 explicit loop, and it's still printing out using string multiplication all of the hashes at once on that row. If you like abstraction and you'd like to wrap your mind more around what the code is doing, well, let's do this.

S1

Speaker 1

04:05:45

If you're not quite clear on what's going on, let's propose that you implement a function called print row, passing in size. And let me propose that this print row function, it simply take in that width and print out the individual hash times that many times. In other words, here's an opportunity for abstraction, whereby, well, what does it mean to print a row? Well, when you're implementing print square, I don't really care what it means to print a row.

S1

Speaker 1

04:06:12

I just need to know that someone's taking care of printing the row. You can kind of pass the buck to another function altogether. And how does print row work? Well, it could use a for loop.

S1

Speaker 1

04:06:23

It could use this string multiplication trick. This is a way to take a larger program, and this is probably the most complicated 1 we've looked at thus far, and to decompose it into these smaller components that, once assembled, achieve your final idea. Seeing no questions, that's the end of our look at loops in Python, this ability to do things cyclically again and again. And when we combine those with conditionals, this ability to ask and answer questions and combine them with our functions and variables, we really now have most of the building blocks we need to solve much larger, much more interesting, much more personal questions.

S1

Speaker 1

04:06:58

So in the weeks to come, we'll start to see exactly what could go wrong, though, when we do so. But we'll introduce you to all the more tools via which you can troubleshoot those same problems. All right. This is CS50's introduction to programming with Python.

S1

Speaker 1

04:07:38

My name is David Malan, and this is our week on exceptions. Exceptions in Python, as well as in other programming languages, refer to problems in your code. Indeed, when something is exceptional in your program, it actually doesn't mean it's a good thing. It means something has gone wrong that ideally you will somehow solve.

S1

Speaker 1

04:07:55

So what are some of the things that can go wrong? So I'm going to go ahead and open up VS Code on my computer here. And in the terminal window, I'm going to go ahead and run code of hello.py. That's going to, of course, open up a brand new tab for me, hello.py, in which I can write my code.

S1

Speaker 1

04:08:09

And let me go ahead and write some very simple code just to say hello to the world. Let's go ahead and say print quote, hello, world. And then let me go ahead and I'm forgetting to close that quote. So a mistake that you yourself might have already made or might surely in the future make.

S1

Speaker 1

04:08:26

And it's a little subtle because you might not necessarily notice that you just missed that 1 character. Well, let me go ahead and somewhat optimistically go down to my terminal window now and run python of hello.py and hit Enter. And that's the first of my errors. My gosh, I've only written 1 line of code, and I seem to have more lines of errors on the screen.

S1

Speaker 1

04:08:44

But the salient point is this bottom-most thing here. Notice where it says syntax error. Syntax error is a problem with the code that you have typed. Your syntax, just like English and other human languages, have syntax associated with them.

S1

Speaker 1

04:08:56

So does my code. And it's not quite correct. Something is awry. I didn't follow the instructions properly.

S1

Speaker 1

04:09:02

And it does elaborate for me, unterminated string literal. Now, that's a bit arcane. That is a bit of a confusing error message. But unterminated would generally mean that I started something but didn't stop it.

S1

Speaker 1

04:09:13

I didn't terminate it. String, of course, is a sequence of text, like we discussed before, or str in Python. And literal generally refers to something that you literally typed. It's not a variable.

S1

Speaker 1

04:09:24

It's something like quote, unquote, or just quote, hello world. So the fix here, of course, is going to be to go ahead and terminate that string and actually close the quote. And if I now go back down into my terminal window and rerun Python of hello.py, now I'm saying hello to the world. So the catch with syntax errors here is that Syntax errors are entirely on you to solve.

S1

Speaker 1

04:09:47

A syntax error is a problem that you've got to go back into your code and fix from the get-go. You can't just kind of hope that it's going to resolve itself or expect that other parts of your code will catch it for you. Syntax errors just must be fixed. But there's a lot of other types of errors in Python that might be described as runtime errors that happen while your code is running.

S1

Speaker 1

04:10:07

And it's really up to you to write some additional code defensively to detect when those errors happen. Because you don't necessarily know, for instance, what input humans are going to type into your program. And so you better be ready defensively to accommodate things that they type or even mistype. So for instance, let's go back over here to VS Code.

S1

Speaker 1

04:10:27

And let me propose that we take a look at a new file altogether. I'm going to close hello.py. And I'm going to write code of, say, number.py. So let's play around with some numbers in Python.

S1

Speaker 1

04:10:38

And the first thing I'm going to go ahead here and do with number.py after opening this new tab is I think I'm going to go ahead and type up a relatively simple program that maybe prompts the user for an integer, like x, and then just prints out what x is. So we're going to start super simple. But again, in starting simple, we'll be able to really see where I've done something wrong. Well, here we go.

S1

Speaker 1

04:10:59

I'm going to go ahead and say a variable called x is going to get assigned the value of the return value of input, quote unquote, what's x question mark. And I'm going to include a space to move the cursor over a little bit. And then ultimately, I'm going to go ahead and, oh, wait a minute. If I'm wanting to get an int from the user, recall that I need to do something proactively.

S1

Speaker 1

04:11:20

I need to actually convert that input to an integer using the int function in Python. So now I'm passing the return value of input as the argument to int, and that will store in x ultimately an integer, not a string that looks like an integer. All right, let me go ahead now and just quite simply print out what this is. I'm going to go ahead and print out quote unquote, x is x.

S1

Speaker 1

04:11:42

But I don't want to literally say x is x. I want to plug in the value of x. So maybe the easiest way to do that is to surround it with curly braces. And then if I'm using these curly braces and I want Python to interpolate the value of that variable, that is, substitute what x actually is in between those curly braces, recall that I need to use a format string or an f string by prefixing this whole thing with an f.

S1

Speaker 1

04:12:04

Now that I've done that, let's go ahead and see what happens. I'm going to go ahead in my terminal window and run Python of number.py. I hit Enter, and so far, so good. All is well.

S1

Speaker 1

04:12:14

I'm being prompted for x. Let me go ahead and type in a number like 50. All right, that seems to work. Program seems to be correct.

S1

Speaker 1

04:12:22

Or is it? What could go wrong in this program, even though nothing did just go wrong? But if I run it and run it and run it again, during the running of my program, what could still go wrong, especially if I'm not the human interacting with it, but some other human instead? Any volunteers here for this 1?

S1

Speaker 1

04:12:44

What could go wrong, and in what way is this program not really correct, even though at first glance it seems so?

S3

Speaker 3

04:12:53

AUDIENCE 2 What is an interpreter? When we code in an integrated IDE, we can't code in an interpreter. DAVID

S1

Speaker 1

04:13:02

MALANYIKA WONGADIMITRIOS So I'm not calling an integer. I'm still having trouble hearing you. But what I think I heard is that if what the user types in is not, in fact, an integer, I can't just blindly convert it to an int.

S1

Speaker 1

04:13:13

If I'm not putting too many words into your mouth, I think what I should perhaps do here is be a little defensive. And let me see if I can't simulate exactly the problem that could go wrong here. Let me go ahead and run, again, Python of number.py. Let me try another number.

S1

Speaker 1

04:13:29

And in fact, when Testing your code, generally, it's a good idea to test corner cases, maybe numbers that aren't quite as plain as 50 or 49 or 51. Let's choose some numbers that might be a little more interesting, if only mathematically, like 0. All right, 0 seems to work. My code still prints out that x is 0.

S1

Speaker 1

04:13:45

What might be another corner case to consider? Well, let me go ahead and try a negative number. That, too, is pretty different in spirit from 50. Negative 1?

S1

Speaker 1

04:13:53

OK, that works, too. Well, let me try it 1 more time. I've tried positive numbers, negative numbers, 0. Let me try something like a cat.

S1

Speaker 1

04:14:00

So literally, C-A-T, typing in a string that doesn't even look like a number. And yet, let's see now what happens when I hit Enter. All right. We'll see now we've got another kind of error.

S1

Speaker 1

04:14:11

It's not a syntax error, because I didn't make a typographical mistake. I didn't forget some piece of syntax, I actually now have a error with 1 of my values. And it's in a value I didn't even anticipate. The human, me in this case, typed it in long after I wrote the code.

S1

Speaker 1

04:14:27

So what does this refer to, a value error? Well, let's see what the explanation is. Invalid literal for int with base 10 quote unquote cat. Now, this too is a bit of a mouthful.

S1

Speaker 1

04:14:36

And unfortunately, in Python and a lot of programming languages, the error messages are written for pretty comfortable programmers. And of course, when you're learning programming for the first time, you might not be so comfortable with the programming language, let alone the error messages. But let's see if we can't glean some insight. So invalid literal.

S1

Speaker 1

04:14:53

Well, again, a literal is just something that's been typed in, it would seem. For int, what is int exactly? Well, int is the function I'm using to convert the user's input to a corresponding integer, base 10. That refers to the decimal system, which is the default that Python's using.

S1

Speaker 1

04:15:10

And it looks like, at the end of the day, what Python really doesn't like is that I passed cat, quote unquote, to the int function. So how do I go about actually fixing this problem? Well, I could just add instructions in my program. Maybe I could add a line of print telling the user more explicitly, be sure to type an integer.

S1

Speaker 1

04:15:28

Or please don't type cat. Please don't type strings. Of course, the user might still not oblige. They might not be reading the instructions.

S1

Speaker 1

04:15:35

So that, too, is probably not an effective strategy. What we really want to do is write our code with error handling in mind. We want to write lines of code that not only accomplish the problems we care about, but that also handle errors that might unexpectedly happen. And in general, when programming, programming defensively.

S1

Speaker 1

04:15:51

Assume that the users aren't going to be paying attention, or worse, they're malicious. They're trying to crash your program. So we want to handle as many errors as we can. Now, how do we go about doing that in Python?

S1

Speaker 1

04:16:02

Well, it turns out, whether you want to catch a value error or other types of errors as well, though not syntax error, Python actually has this keyword called try. And it's sort of aptly named. If you want to try to do something in Python, you can literally use this keyword and you can check whether or not something exceptional, something erroneous has happened. So using both try and this other keyword except, can I go and try to do something except if something goes wrong, I can do something else instead?

S1

Speaker 1

04:16:32

So let's consider, how can I go about trying to convert the user's input to an int, except if something goes wrong? Well, let me go back to my code here. And let me propose that I now modify this example as follows. Let me go ahead and above my first line of code, I literally write try and a colon telling Python try to do the following.

S1

Speaker 1

04:16:51

I'm going to go ahead and indent my existing lines of codes here by the same number of spaces, 4 in this case. And then I'm going to add 1 more new line down here that literally says, accept value error. And notice it's important that I've capitalized the V and I've capitalized the E. These symbols are case sensitive.

S1

Speaker 1

04:17:09

And this is now an opportunity, after this colon, to tell Python what I want to do in exceptional cases, when the number or the input from the user is not, in fact, a number. And I'm going to say something plain like, print, quote unquote, x is not an integer. I'm at least going to tell the user roughly what the problem actually is. So notice another detail.

S1

Speaker 1

04:17:31

The indentation is important. Because I have try on line 1 and I've indented lines 2 and 3, those are the 2 lines of code that I'm trying. Except if I see a value error, line 5, because it's indented, is what is going to get executed in cases of those errors. Let me go ahead now back to my terminal window and run Python of number.py, Enter.

S1

Speaker 1

04:17:54

And let's go ahead and type in 50 again. Still seems to work. And of course, I'm trying and succeeding. Let me go ahead and try once more, this time, though, with the word cat, or really anything that's not a decimal number.

S1

Speaker 1

04:18:05

And now you'll see much more cleanly x is not an integer. I'm not seeing some scary error message that I, as a user, am going to have no idea how to handle. Now You, the programmer, have anticipated that something exceptional can happen, and you've gone about actually handling the error for the user, giving them an appropriate error message instead. Let me pause here and see, are there any questions now on what we've just done by introducing try and accept to handle this value error.

S3

Speaker 3

04:18:35

Is value error the only type of error you can get, or the other types?

S1

Speaker 1

04:18:39

Is value error the only thing you can catch? There are other errors as well. And we'll see a few of them today.

S1

Speaker 1

04:18:43

And there's many, many more, honestly, that if you continue programming and programming in Python, you're going to see a lot of them over the weeks, the months, the years to come. But the technique for handling them is going to be largely the same. Other questions on try, accept, or these exceptions more generally?

S3

Speaker 3

04:18:59

Yes. Sir, actually, to use the accept block, you need to know the type of error, right? Like here, you knew it was a value error. What if you can't anticipate this particular type of the error?

S1

Speaker 1

04:19:11

A really good question. So I'm being very good about catching, so to speak, the very error that I know might happen. I don't know when it might happen, because it's going to depend on the user.

S1

Speaker 1

04:19:21

But I know what kind of error will happen from the int function. There is a way in Python where you can say, except if anything goes wrong. And you can literally omit value error and just catch everything. The problem with that is that it sometimes hides other bugs in your code because you don't necessarily know what's going wrong.

S1

Speaker 1

04:19:40

And if you don't necessarily know what's going wrong, how can you possibly handle it correctly? So bad practice. And put another way, it's lazy to do that, to just say, catch everything and I'll deal with it here. So a much better practice would be to figure out what kind of errors could happen and include mention of them explicitly, as I've done.

S1

Speaker 1

04:19:58

Now, with that said, if you read Python's official documentation, as you'll eventually invariably do, it is not great about telling you proactively what kinds of errors can be raised in this way. So it's a bit of contradictory advice. You should do it this way, but It's not always obvious what you should be checking for, but you get better at it with practice. And some of the times the documentation does spell out what could go wrong.

S1

Speaker 1

04:20:22

Let me turn our attention now back to this and point out that even though this is better code, it is more correct in the sense that I'm not just leaving it to the user to see some really ugly default Python error message that most people are going to have no idea what to do with. I'm at least handling it more elegantly. And I'm printing out x is not an integer. So it's at least more instructive.

S1

Speaker 1

04:20:43

But this isn't necessarily the best way to implement this code. Why? Well, here, too, I'm actually still being a little lazy. So notice that I'm trying to do not 1 line of code, but 2 lines of code.

S1

Speaker 1

04:20:54

And this isn't a huge deal, because we're only talking about 2 lines of code. But in the interest of preaching best practices, you should really only be trying to do the 1 or very few lines of code that can actually raise an exception, that can actually fail in some way. I am pretty sure that calling print here is not going to raise a value error. Whether x is an int or a string or a float or anything else, the format string feature of Python is going to handle printing it just fine.

S1

Speaker 1

04:21:25

So really, what I'm going to do is this. I'm going to move this line 3 down to the bottom of my code. I no longer need to indent it. I'm just going to execute it at the bottom of my file here.

S1

Speaker 1

04:21:36

Unfortunately, by doing this, I've done a good thing by now only trying to do the minimal amount of work necessary that might raise the exception, a value error. But I fear I've introduced a new mistake. Well, let's see. What is now incorrect?

S1

Speaker 1

04:21:50

Let me go ahead and again run Python of number.py, Enter. Let me go ahead and do it correctly with 50, and all seems to be well. But again, let's try those corner cases, the zeros, the negative numbers, or in this case, the cat. Let me go ahead and type in C-A-T again, Enter.

S1

Speaker 1

04:22:06

Now I have a name error. So now it's yet another type of error in my code that I've introduced here. And what does this name error mean? Well, just as a value error refers to that, the value of some variable, the value that someone has typed in is incorrect, name error tends to refer to your code.

S1

Speaker 1

04:22:22

Like you're doing something with the name of a variable that you shouldn't. And why might that be? Well, let me turn our attention back to the code here and consider, what is it complaining about? Well, the name error is what I see down here.

S1

Speaker 1

04:22:34

And it's telling me name, quote unquote, x is not defined. And notice, if I look further here, it is mentioning line 6. So I know the problem is with my code on line 6. And that worked a moment ago.

S1

Speaker 1

04:22:48

And I'm defining x on line 2. But let me ask the group here, why does x not, in fact, exist on line 6? Why is it not defined, even though I'm pretty sure I was intending to define it on line 2.

S3

Speaker 3

04:23:04

AUDIENCE 1. Maybe the scope of the variable is between the dry block.

S1

Speaker 1

04:23:10

DAVID MALAN So good terminology. Scope refers to the portion of code in which a variable exists. That, too, though, isn't quite right in Python.

S1

Speaker 1

04:23:18

That would be true in C, C++, and Java, where indentation or curly braces tend to define the scope of a variable. But again, here in general, and this worked a moment ago, x exists once it's defined on line 2. Because remember, I printed out x is 50 a little bit ago. Let's try 1 more hypothesis here.

S1

Speaker 1

04:23:38

1 more hand. Why is x somehow still not defined?

S2

Speaker 2

04:23:42

AUDIENCE 2 Yeah, so is it because It's local variable, meaning that it doesn't define outside of scope. It's like what people have mentioned. It prompts the input in try, right?

S2

Speaker 2

04:23:55

But outside of it, it's undefined.

S1

Speaker 1

04:23:57

DAVID MALAN So still good instincts and good terminology, too. There's this notion of local variables, which tend to exist inside of functions, for instance, global variables, which tend to exist in entire files. In this case, too, though, that's not quite the case.

S1

Speaker 1

04:24:09

What's happening here boils down to order of operations. Let me come back to the code here and Recall that any time we've discussed the assignment operator, the single equal sign, that copies a value from the right to the left. But consider for a moment at what point something is going wrong. Well, the input function is probably working just fine because we've used that a lot now to get users input.

S1

Speaker 1

04:24:30

It always returns a string or a str in Python. But what could be going wrong? Well, if I'm passing that string to the int function as its argument, it's probably the int function that's erring. And indeed, if you think back earlier when we had the value error, it was, in fact, the int function that did not like quote unquote cat as input.

S1

Speaker 1

04:24:52

So this is all to say that this portion of my code highlighted now to the right of the equal sign, that's the code that's creating a problem. That's the code that was creating a value error. And in this case, we're catching the value error. But because the value error is happening on the right of the equal sign, there's no value being copied to the left.

S1

Speaker 1

04:25:13

The error is interrupting that whole process. So even though we see x equals dot, dot, dot on line 2, the portion of that line to the left of the equal sign isn't getting evaluated ultimately because the value error is happening too soon. And so when we finally get down to line 6, even though it looked like I was defining on line 2 and I would have defined x on line 2 if all had gone well, we didn't get to the part where the value is copied from right to left because the value error happened first. So this code is just incorrect now.

S1

Speaker 1

04:25:44

So how do I go about solving something like this? Well, it turns out that there's another feature of the try and accept syntax that Python supports, which is that it also supports the keyword else. Now, we've seen else before. If you think back to our discussion of conditionals, We saw if, we saw elif, we saw else, which was kind of this catch all, what you should do in the event that nothing else is relevant.

S1

Speaker 1

04:26:08

That's kind of the same intuition here for the try, accept feature of Python. What you can do is this. You can try to do the following, as I've done, except if this goes wrong. But if nothing goes wrong, else go ahead and do this.

S1

Speaker 1

04:26:23

So this is 1 way I can solve this same problem now. No matter what now, Python is going to try to execute line 2. If something goes wrong, it's going to execute lines 3 and 4 to handle that value error. However, if you try and this code succeeds, then there is no exception to handle.

S1

Speaker 1

04:26:42

So you're then going to execute this line here. So it's a little confusing, perhaps, in that we're now using else both for conditionals, if, elif, elif, elif, else. And we're also using else with these try, except blocks. But that's OK.

S1

Speaker 1

04:26:56

That's part of the language. That's 1 of the features. So now if I rerun this code in my terminal window, Python of number.py, let's do something correct, like 50, I see that x is 50. So line 1 is executed.

S1

Speaker 1

04:27:10

We're trying to do the following. Line 2 is executed because the conversion happened successfully and the number 50 gets copied from right to left. The exception does not happen. So we ignore lines 3 and 4.

S1

Speaker 1

04:27:21

We jump immediately to line 5 and 6, which prints out the result. By contrast, though, let's do this 1 last time. Python of number.py, let's type in cat, or again, any other word, and hit Enter now. We don't see what x is.

S1

Speaker 1

04:27:35

Rather, we see, quote unquote, x is not an integer, which is what's being handled in my accept clause. All right, let me pause here, because that's a lot of new syntax, and see here if there's any questions on try, on accept, on else, name error, or value error.

S3

Speaker 3

04:27:53

Can you please repeat the try function?

S1

Speaker 1

04:27:56

Repeat the name error. What's the problem with the name error?

S3

Speaker 3

04:27:58

Yes, yes.

S1

Speaker 1

04:27:59

Yeah, so Let's just rewind a couple of lines here before I fix this problem by now getting rid of the else. A moment ago, we had code that looked like this, whereby I was getting a name error, Python of number.py, Enter, typing in cat, that looked like this, where name x is not defined, and the problem was on line 6, according to this output in Python. Well, let's think about this now deductively.

S1

Speaker 1

04:28:23

Let's try a different approach. On line 6, I'm seeing an error that name x is not defined. OK, Python's already telling me x does not exist at that point. So how could that possibly be?

S1

Speaker 1

04:28:33

Well, where should x be defined? Well, presumably, x is defined on line 2 up here. So what could go wrong? Well, if the user has inputted something that doesn't look like a number, like the word cat, passing cat, the return value of input, as the argument to int to convert the word to an int makes no sense.

S1

Speaker 1

04:28:55

You can't convert a cat, C-A-T, to an integer at all. So the int function is raising a value error at that point, and the error is being handled with this code here. But notice, this line 6 is not indented. It's left aligned with the rest of my code, which means no matter what, line 6 is going to execute.

S1

Speaker 1

04:29:18

It's going to execute whether I typed in 50 or I typed in cat. But if I typed in cat, again, x never gets a value, so it's not defined here on line 6. So when I introduced, finally, the else statement, that makes sure that these things are mutually exclusive. I only execute the else if I tried and succeeded up above.

S1

Speaker 1

04:29:40

Well, let me propose that we refine this just a little bit further as well and consider how we might improve this example a little bit more. It's a little unfriendly of me to be rejecting the user's input after they fail to provide an integer and just quitting the program, really. It'd be more user-friendly if I just prompt or re-prompt the user again and again. And in the chat, if you could, what's the feature of Python that you can use if you want to do something again and again and again until such time as the user cooperates and gives you what you're looking for, like a number.

S1

Speaker 1

04:30:17

So yeah, loop, loop, loop. So a loop is something that happens again and again and again. And maybe we can use that same mechanism, a loop, in order to prompt the user for x. And if they don't give us a number, prompt them again.

S1

Speaker 1

04:30:29

And if they don't, prompt them again and again and again. We don't need to just quit out of the program so quickly. So let me propose this. Let me propose here that I improve this code by deliberately doing this.

S1

Speaker 1

04:30:40

Let me induce a infinite loop at the very top of my code with while true. Recall that the while keyword induces a loop, a cycle that behaves like this, and it asks a question, a Boolean expression that needs to evaluate either to true or false. Well, if I want this thing to loop forever, at least initially, we'll just say while true, because true is true. So this has the effect of doing something no matter what forever, unless we break out of it early.

S1

Speaker 1

04:31:06

Now I'm going to go ahead and do this. I'm going to go ahead and move my try except code indented underneath this loop so that I'm trying to get an x. If I have a value error instead, I print out x is not an integer. But this time, what do I want to do if the user does try and succeed in giving me a number?

S1

Speaker 1

04:31:28

Well, I can do this. I can just break out of my code here. And down here now, I can use that same line of code from before, an f string that says x is, and then in curly braces, x again. So what's going on here?

S1

Speaker 1

04:31:42

I think this code now, because I've added the loop, is going to have the effect of trying at least once, maybe a second time, maybe a third time, maybe 500 times until the user finally gives me what I want, which is an integer. And once they do, once there's no value error happening, Then I break out of the loop, and line 9 executes as I would hope. So let me go ahead and try executing this version. Python of number dot pi, Enter.

S1

Speaker 1

04:32:09

What's x? Let me go ahead and type in the easy thing first, 50. X is 50. What just happened in terms of the control flow of this program, the flow of my logic.

S1

Speaker 1

04:32:18

Well, I first found myself on line 1 inside of a loop. Hopefully, I'll get out of this loop. What did I then do? On lines 2 and 3, I tried to get input from the user and convert it to an int.

S1

Speaker 1

04:32:29

Well, I was a nice guy this time, and I typed in 50, which looks like and is a number. So the int function converted it just fine and stored it from right to left in x. Except value error, there is no value error. Because if I typed in a number, there's nothing exceptional happening.

S1

Speaker 1

04:32:43

This is a boring, good execution of my program. So what happens? I break out of the loop. So again, the else clause is associated with the try, not with the accept.

S1

Speaker 1

04:32:54

And once I'm out of the loop, of course, I'm just printing out what x is. Well, let's try the other scenario that might happen. Python of number.py, Enter. What's x?

S1

Speaker 1

04:33:03

Let's try cat or any other word. Enter. Ah, this is now a new feature. I'm being informed what I did wrong.

S1

Speaker 1

04:33:11

X is not an integer. So I'm getting some useful user feedback. But notice, again, I'm prompted what's x. Well, let me try typing in dog.

S1

Speaker 1

04:33:19

X is not an integer. What's x? Let me try bird. Enter.

S1

Speaker 1

04:33:24

X is not an integer. What's x? And suffice it to say, this will happen now forever, if I'm in an infinite loop, until I try and succeed, at which point I break out. So let's try again.

S1

Speaker 1

04:33:34

50, Enter. Now I'm out of the loop, and I'm printing out what x actually is. All right, let me pause here and see if there are any questions. The logic is almost the same, but what is different now is I'm in a loop, and I'm using the keyword break in Python to deliberately break out of the loop when I'm ready to, once the user has cooperated.

S3

Speaker 3

04:33:56

We really need to break? Can't we just print? Or what keeps us from just printing?

S3

Speaker 3

04:34:03

DAVID MALAN GALLAGHERA

S1

Speaker 1

04:34:04

Good question. So let me try that. Couldn't I just print?

S1

Speaker 1

04:34:07

Well, let's see what happens if I do that. Let me move this print line at the end into my loop here, thereby shortening the program. And in general, That's been a good thing. Python of number.py, Enter.

S1

Speaker 1

04:34:18

Let me go ahead and type in 50. OK, x is 50. What's x? OK, maybe it's 49.

S1

Speaker 1

04:34:24

X is 49. OK, maybe 48. Unfortunately, I think you're laughing. You see it.

S1

Speaker 1

04:34:29

I never break out of the loop, which maybe that's a feature. Maybe you want this to be your program. But I didn't. I'd eventually like this game to stop.

S1

Speaker 1

04:34:35

So I need to break out in that way. But I can do it a little differently. And let me propose that we modify this a little bit. But first, any other questions on this syntax here?

S1

Speaker 1

04:34:46

Let me rewind to the prior version.

S4

Speaker 4

04:34:51

Hi. Can I use break all in exception except in else? For example, in another print, when you use print in the else, you can use print together with break or something like this?

S1

Speaker 1

04:35:05

DAVID MALAN So you can use break inside of loops, to break out of loops. And you can use it inside of a conditional, like an if, an elif, or an else. You can do it inside of a try, accept, else statement, too.

S1

Speaker 1

04:35:16

Anytime you're in a loop that you want to break out of, you can use this keyword break. I'm using it in the context of exceptions, but it's not restricted to that. And let me show you, too. It doesn't even have to be in the else.

S1

Speaker 1

04:35:27

If I wanted to, I could actually do this. I could get rid of my else, and I could go back to line 3, add another line that's indented, line 4, and break out here. Now, why is this logically OK? Well, consider what I'm now trying to do.

S1

Speaker 1

04:35:44

I'm trying to execute line 3 and converting the user's input to an int, and I'm trying to store the result from right to left in x. If something goes wrong, the code we've already seen is immediately going to jump to line 5 and then 6 to handle the exception. But if nothing goes wrong, my code presumably should just keep on executing line by line. So I could technically, logically put the break here.

S1

Speaker 1

04:36:10

And watch what happens when I run this version. Python of number.py, 50, Enter. It worked. I broke out of the loop.

S1

Speaker 1

04:36:18

Now, which way is better? Honestly, I think it could go either way at this point. This program is so relatively short that even though I'm trying to do 2 things now, 1 of which, the break, is not going to fail. Like, you either break or you don't.

S1

Speaker 1

04:36:31

There's no piece of data from the user that's going to influence that. We don't strictly need to have those 2 lines of code there, but it's only 2 lines, so I think it's OK. And if you recall our discussion in the past, not just of correctness, does the code work as it should, but design, I think you could argue it either way. If you prefer the readability of this and the fact that you don't have an else, that's fine.

S1

Speaker 1

04:36:51

If, though, you prefer to minimize just how many lines of code you're trying to execute in case something goes wrong, the else is a reasonable approach, too. Well, allow me to propose, too, now that we refine this further. I think we're at the point where it's pretty darn correct. But suppose now that I find myself today and tomorrow trying to get numbers from the user quite a bit.

S1

Speaker 1

04:37:12

It would be nice, as we've seen, to maybe just invent my own function, getInt, to get an integer from the user, both today and tomorrow and beyond. And heck, maybe I can even share that function with other people if they want to write programs that get integers from users. So how might I go about doing this? Well, let me go ahead and propose that we do this.

S1

Speaker 1

04:37:29

Let me get rid of the print line but keep most of my loop here. Let me define a function called getInt that takes no arguments for now. And I'm going to go ahead and indent all of the code I already wrote underneath getInt. So now I have a function called getInt that tries to do the following.

S1

Speaker 1

04:37:47

Try to get an int from the user. If something goes wrong and there's a value error, yell at them with x is not an integer. Else, break. But it's not just breaking that I want to do here.

S1

Speaker 1

04:37:57

Now that I'm in a function, recall our discussion of return values. If you're inventing your own function whose purpose in life isn't just to print something on the screen like a side effect, but is to hand back a value, to hand you back a value, like on that same Post-it note from our discussion of functions, Well, you need to return x explicitly. How do I now use this function? Well, as soon as we start making our own functions, it tends to be convenient to define our own main function as well.

S1

Speaker 1

04:38:24

That's the main part of our program. And I'm going to keep this simple. I'm now going to say x equals get int. And then on the next line, I'm going to do that print from before, quote unquote, x is, in curly braces, x.

S1

Speaker 1

04:38:36

And at the very bottom of my program, recall, I'm going to call main so that no matter what, I'm invoking my main function after everything's been defined. Well, let's see how this works. Let me go ahead and run Python of number.py, Enter. Let's type in 50.

S1

Speaker 1

04:38:51

And it seems to work as before. Let's go ahead and run it again, typing in cat, C-A-T, this time. X is not an integer, and I'm being prompted. Dog, and I'm being prompted.

S1

Speaker 1

04:39:01

Bird, and I'm being prompted. Fine, fine, fine. 50. That's an int, and so it is printed.

S1

Speaker 1

04:39:07

So what's worth noting here, while I'm manifesting a couple of good properties here, 1, I've kind of abstracted away this notion of getting an integer. And even though I just artificially hit Enter a whole bunch of times just to hide that function for now, it needs to be there, but we don't need to see it at this point. Notice that now this entire program really boils down to just these 3 lines of code now. Why?

S1

Speaker 1

04:39:28

Because I've abstracted away that whole process of getting an int from the user into this new function of my own called getInt. But can I improve upon this? Well, let me go ahead and undo all of those blank lines and pull this up just so we can see more on the screen at once. Can I tighten up my implementation of getInt?

S1

Speaker 1

04:39:45

It is correct. I claim this is correct. It's handling errors, and it's returning x. But I don't, strictly speaking, need to write the code as long.

S1

Speaker 1

04:39:53

What else could I do? Well, let me propose that if all you're doing on this line 13 is breaking, and then immediately after that, per the indentation, you're executing return x on line 14, why are you wasting everyone's time? Once you know you're ready to return the value, you could just return x. And so in my else, I could break out and return a value.

S1

Speaker 1

04:40:13

So here, too, Return is used to return values from functions. Break is used to break out of loops. But it turns out that return is sort of stronger than break. It will not only break you out of a loop, it will also return a value for you.

S1

Speaker 1

04:40:30

So it's doing 2 things for once, if you will. But can I make this even more compact? If my goal is to just tighten the code up, even though it's already correct, can anyone think of a further refinement, Whether you've programmed in Python before or not, can I shorten this implementation further just a little bit, if only to decrease the probability that I've made a mistake by having fewer lines and just make it a little easier to read because it's shorter? Any suggestions for tightening up my implementation of get int?

S3

Speaker 3

04:41:03

You can just return the value on the try function when you're trying. You take the input x and then return x.

S1

Speaker 1

04:41:12

Good. We can just return x a little higher up. And let me correct folks as we go. It's not a try function.

S1

Speaker 1

04:41:17

It would be a try statement, technically. A function typically has a parenthesis and another 1. In this case, it's just a statement. But we can do exactly that.

S1

Speaker 1

04:41:25

I don't technically need the else. If I really want, I could do this. Right after line 9, I could return x here. Or recall our discussion of defining variables unnecessarily sometimes.

S1

Speaker 1

04:41:37

Like, why define a variable here if you're immediately going to use it here and then never again? So we could avoid a new line here. And I could avoid even defining x explicitly. I could just say something like this.

S1

Speaker 1

04:41:49

I could return int input quote unquote what's x. I can do it all at once. Now, which is better? I don't know.

S1

Speaker 1

04:41:57

I mean, again, this is where reasonable people might disagree. I'd argue that on the 1 hand, we're tightening up the code. We're using fewer lines. It's easier to read.

S1

Speaker 1

04:42:05

There were probability that I've made a mistake. On the other hand, it's a little more complicated to understand, perhaps. It's a little less obvious where I'm returning from. So I think arguments can be made either way.

S1

Speaker 1

04:42:16

At the end of the day, what's important is that you've done this consciously. You've made a decision to do it this way or this way. And you can justify it in your mind, not that your answer is, it worked, so I left it alone. Like, have a good reason.

S1

Speaker 1

04:42:28

Come up with a good reason. And that will come with experience and practice. Well, let me propose, too, that we make 1 other refinement here. Suppose that you're finding your programs to be a little noisy, and it's a little obnoxious that you keep telling the user x is not an integer, x is not an integer, x is not an integer.

S1

Speaker 1

04:42:44

What if you want to make things a little gentler and just prompt the user again with the same words, what's x, what is x, what's x, again and again? Well, you can do that as well. And it turns out that if you want to handle an exception in Python, but you want to pass on doing anything with it. So you want to catch it, but you essentially want to ignore it.

S1

Speaker 1

04:43:06

You don't want to print anything. You don't want to quit the program. You just want to silently ignore it, like if you're talking in a room full of people, and it's your turn to talk, and you're just like, pass. They're still calling on you, but you're not doing or saying anything more.

S1

Speaker 1

04:43:20

Well, we can add this keyword to our code here. Let me go back to my program here. And instead of printing out again and again, x is not an integer, I could just do this. I could pass on handling the error further.

S1

Speaker 1

04:43:33

I'm still catching it. So the user is not going to see a scary message even mentioning value error. My code is catching it, but I'm passing on saying anything about it. I'm going to stay in the loop.

S1

Speaker 1

04:43:43

I'm going to stay in the loop and keep prompting and re-prompting the user. So now the effect looks a little something like this. Python of number.py. Let's type in cat.

S1

Speaker 1

04:43:52

What's x again? Let's type in dog. What's x again? Type in bird.

S1

Speaker 1

04:43:56

So it's just a little maybe more user-friendly in that you're just reminding the user what you want. Maybe it's worse. Maybe it would be helpful to tell the user why you're prompting them again and again. It's not obvious.

S1

Speaker 1

04:44:07

So it could go both ways. But again, it's just another mechanism now for handling these errors. We use the accept keyword to catch a specific error. But we don't have to handle it more than that.

S1

Speaker 1

04:44:17

We can just pass on doing something further. Let me pause here and see if there's any questions now on try, accept, else, or pass.

S5

Speaker 5

04:44:27

OK, yeah, no, I was just kind of curious, I guess, about the idea of when you were indenting with the getInt function, for example. Because I'm noticing, obviously, going through it with the whole logic and breakdown of the entire function, while true, do this. But I'm just kind of curious on elaborating with the indentations for the code more.

S5

Speaker 5

04:44:48

DAVID MALAN HANSON-COHEN

S1

Speaker 1

04:44:49

Yeah, so the indentation is deliberate logically. Some languages don't require as rigorous indentation. You can use curly braces or other symbology to make clear what is associated with what.

S1

Speaker 1

04:45:00

In general, any time you indent something in Python on this line, rather, any time you write a line of code in Python that's here and the lines below it are somehow indented, that means that those lines are somehow associated with that first line. And Presumably, those indented lines should only be executed if the first line told the computer to do so. So concretely, what does this mean? On line 6 here, we're defining a function called getInt that takes no arguments, colon.

S1

Speaker 1

04:45:30

Everything that's indented by at least 4 spaces hereafter is part of that function. Why? That's just the design of the Python language. Frankly, I think the designers got tired of seeing really ugly code in languages like C and C++ and Java that don't necessarily enforce indentation to this extent.

S1

Speaker 1

04:45:51

So now it's baked into the language. And my chronology might be a little off there, but there's been many languages that are looser than Python when it comes to indentation. The indentation is meaningful on line 7-2. Notice that because the while true is indented by 4 spaces, that just means it's part of the get int function.

S1

Speaker 1

04:46:07

But notice below the while true statement, there's 8, there's 12, there's 8, there's 12 spaces here. And I'm just quickly counting the dots. That means that all of the lines I've just highlighted are inside of that while loop. While true means to execute lines 8 through 11, potentially, again and again and again.

S1

Speaker 1

04:46:24

And now lastly, on line 8, because we have try and indented below it is line 9, That just means that what you should try is what's on line 9. And similarly, on line 10, below it, we have indented line 11. You should only pass when there is an exception of a value error. So the indentation just means what is associated with what.

S1

Speaker 1

04:46:47

And once you get comfortable with that, you'll see that it helps. The indentation alone helps explain the logic of your program. And it has a wonderful side effect that for yourself the next morning, for your colleagues, your family, your friends, your teachers, your code is much more readable as a result. It's not 1 big mess of a blob of text.

S1

Speaker 1

04:47:05

Other questions now on try, except else or pass.

S3

Speaker 3

04:47:10

Yeah, thanks. 2 questions. Question 1, Once you say pass, can the caller still learn anything about this error through a system variable or whatever?

S3

Speaker 3

04:47:24

And question 2, problem set 0 referenced some string methods, including isNumeric. Is it any different to go via isNumeric here? DAVID MALAN

S1

Speaker 1

04:47:37

ANDERSON Good question. So on the first question, if I'm handling the error in this way, the caller is not going to know anything about it. That's the point of my handling it, so that main or other callers don't know that anything technically went wrong.

S1

Speaker 1

04:47:49

On the second question, isNumeric is another function that you can call that can look at a string and determine, is this, in fact, a number? I could use a mechanism like that. I could use a conditional. If this looks like a number, then pass it to the int function and go ahead and convert it to an integer.

S1

Speaker 1

04:48:06

That's totally fine. I would generally say that the Pythonic way of doing things is often, for better or for worse, to try things, hope they work, but if they don't, handle the exception. So other languages are more in favor of checking if, if, if, if, elif, else, and all of these conditionals. Python tends to be a little more of the mindset, try it, but just make sure you're handling the error.

S1

Speaker 1

04:48:31

So this would be the Pythonic way of doing it. Your way, though, checking with a conditional, is it a number first, is totally reasonable, too, if you want to go that way. Well, let me propose some final refinements to this program that really just kind of tighten things up 1 additional step to improve the implementation of this getInt function, let me propose that we not hard code, so to speak, that is, type manually x all over the place. Let's make this function getInt a little more reusable.

S1

Speaker 1

04:48:59

Right now, notice that I'm just kind of using the honor system that, well, main is defining a variable called x, and getInt is asking for a variable called x. But it would be nice if the caller, main, doesn't have to know what the callee is naming its variables and vice versa. So caller, to call a function means to use it. The caller is the function that's using it.

S1

Speaker 1

04:49:21

The callee is just the function being called. It would be nice if I'm not just hoping that x is the same in both places. So let me propose this. Let me propose that we actually add a parameter to getInt like this.

S1

Speaker 1

04:49:37

What's x? That is to say, if main wants to use the getInt function, well, then main should probably tell the getInt function what prompt to show the user. Just like the input function, recall, that comes with Python, it's up to you to pass in a prompt that the user then sees when the human is asked for input. So how do I make this work here?

S1

Speaker 1

04:49:57

I can go down to my definition of getInt, and I can say, All right, getInt is going to take a parameter now called prompt. I could call it anything I want, but prompt in English is pretty self-explanatory. It means what do you want the message the user will see. And now down here when I actually use input, I don't have to presumptuously say what's x, because what if the program, the caller, wants to ask for y or z or some other variable?

S1

Speaker 1

04:50:20

I can just pass to input whatever prompt the caller has provided. So now I'm making more reusable code. It still works just the same. I haven't changed the functionality, per se, but now it's a little more dynamic because now getInt doesn't have to know or care what variable is being asked for, what's being asked for.

S1

Speaker 1

04:50:39

It just needs to know what prompt it should show to the user. So if I now run this program down here again, prompt number.py, Enter, What's x? 50. Still seems to work.

S1

Speaker 1

04:50:50

Let's run it again. Let's type in cat. It still seems to work. And if I type in cat, dog, bird, or anything else, it will keep prompting me with that same prompt, making this code, therefore, all the more usable.

S1

Speaker 1

04:51:01

Now, it turns out, too, you can even raise exceptions yourself using Python's raise keyword. But more on that another time. So in the coming days, the coming weeks, the coming months, as you write more code in Python, you'll see that errors are inevitable. Sometimes there's syntax errors, which you've got to just fix if you even want to run your program at all.

S1

Speaker 1

04:51:20

But they could be name errors, for instance, variables that you meant to define but somehow didn't, value errors where maybe the user didn't cooperate and provided you with something that you weren't expecting, or a whole list of other possible errors or exceptions. But now, hopefully, you know how you can handle these errors and respond to them in any way you like. This, then, was our look at exceptions. And we'll see you next time.

S1

Speaker 1

04:52:09

All right. This is CS50's introduction to programming with Python. My name is David Malan, And this is our week on libraries. So libraries are generally files of code that other people have written that you can use in your own programs, or a library's code that you've written that you can use in your own program, but maybe not just this program, but another and another as well.

S1

Speaker 1

04:52:30

So Python supports exactly this idea, this ability to share code with others, share code across your own projects, and it does so by way of what it calls module. A module in Python is just a library that typically has 1 or more functions or other features built into it. Generally, the purpose of a library, or a module specifically, is to encourage reusability of code. If you find yourself using the same types of functions again and again, the same functionality, if you find yourself copying and pasting from an old project into your new project, odds are there's an opportunity there to factor out that code that you keep copying and pasting, that you keep reusing, and put it into a library that you can then load into your programs moving forward, so as to not just copy and paste it and have all these different copies all over.

S1

Speaker 1

04:53:17

So what are some of the modules or libraries that Python comes with? Well, Python comes with a random library, literally, which is to say that when you install the Python interpreter on your Mac or PC or somewhere in the cloud, Not only do you get Python, you get a whole bunch of modules as well. Now, these modules provide you with functions that you don't have access to just by default, like you do print and input. Print and input and other such functions just work in Python.

S1

Speaker 1

04:53:43

But sometimes functions are tucked away in these modules, So you have to be more deliberate about loading them into the computer's memory. So somewhere on the computer's hard drive, once you've installed Python, there is also, it turns out, a file, probably called random.py, that someone else wrote, probably long ago, but that you have access to. And in that random.py file, there's probably 1 or more functions that you yourself can use in order to do things randomly. That is to say, how could you flip a coin in a program in Python?

S1

Speaker 1

04:54:14

How could you pick a random number between 1 and 10 in Python. Well, you need a bit of randomness. And while you could figure out mathematically how to write functions like that yourself, it's a lot easier to stand on the shoulders of others who've already solved that problem for you so you can focus on the problem that you yourself want to solve. So for documentation on most any Python module, you go to the official Python docs, and you go to a URL like this where the documentation for that specific module lives.

S1

Speaker 1

04:54:43

And within the documentation, you'll see a list of the functions or other functionality that some module provides. But how do you go about loading a module into your own program so that you can use the functions in that module? Well, we need a new keyword in Python, and namely, it's import. The import keyword in Python allows you to import the contents of the functions from some module in Python.

S1

Speaker 1

04:55:08

Well, how might I go about using this in practice? Well, let me propose that there exists in that random module this function, among others. So I have copied and pasted from the documentation this summary of a function called choice. Now, the function exists in the random module, so to speak.

S1

Speaker 1

04:55:27

Not a random module, the random module. And so generally, the documentation describes it fully like this. Random.choice is how you would technically call this function, though we'll see alternatives to that. In parentheses, there is a parameter called seq for sequence.

S1

Speaker 1

04:55:43

And sequence generally means a list or something that is list-like, if you have a list of numbers or strings or anything else. And the documentation elaborates. Well, how can I go about using this function to solve perhaps a familiar problem? Well, let me go ahead and open up VS Code here.

S1

Speaker 1

04:55:58

And let me propose that we implement a program that simulates flipping a coin, a coin that in the US heads heads or tails, the idea of which is to pick a decision with 50-50 probability, 50% probability of heads, 50% probability of tails. Or you can use some other mechanism like that. Well, let me go ahead and open a program with code called generate.py, because I want to start generating a whole bunch of random information, the first of which is just going to be a coin toss. Now, how do I go about using that function?

S1

Speaker 1

04:56:29

Well, I first have to import the random library. So literally, the first or among the first lines of my file should be import random. And that just gives me access to all of the functions in that specific module. Now suppose I want to flip a coin.

S1

Speaker 1

04:56:44

Well, I can do random.choice per the documentation a moment ago. And that, again, takes a sequence. What's a sequence? It's a list or something that's list-like.

S1

Speaker 1

04:56:52

And we know about lists. We've used lists to iterate over numbers. We've used lists to iterate over students at Hogwarts. Let's go ahead now and iterate over just a list of 2 sides of a coin, heads, quote unquote, or tails.

S1

Speaker 1

04:57:05

Now, I could call these anything I want. These are my strings. I just want to simulate a tossing a coin. So I'm just going to say in all lowercase, heads and tails.

S1

Speaker 1

04:57:13

But notice the syntax. I have heads and tails in double quotes. That's because they're strings. I could also use single quotes, so long as I'm consistent.

S1

Speaker 1

04:57:21

There's a comma between them, which means the list has 2 elements. There's square brackets to the right and the left, which indicates that this is indeed a list. That's the syntax recall for defining a list in Python. And then lastly, there's something more familiar.

S1

Speaker 1

04:57:34

There's the parentheses outside of those square brackets. But those are just the parentheses that belong to the choice function and specify where its parameter gets passed in. But again, unlike past functions, I have to specify what module this function is in, at least for now. And so I do random.choice to call this specific function.

S1

Speaker 1

04:57:54

All right, well, it's 1 thing to flip a coin, picking between those with 50% probability. And that's what random.choice does. It takes in a list, and it returns to you 1 of those values randomly with equal probability. Because I've passed in 2 items, I've got a 50-50 chance.

S1

Speaker 1

04:58:09

If I passed in 3 items, it'd be a 33% chance for each of those items and so forth. Python does the math for you. But I want to store the value of this in a variable. So let's define a variable called coin equals whatever the return value is.

S1

Speaker 1

04:58:22

So this is indeed like flipping a coin. I'm going to store in a variable called coin whatever that value is, heads or tails. And now, just so I can see what's going on, let's go ahead and print out the value of that string coin. All right.

S1

Speaker 1

04:58:34

Let me go ahead now and run this program in my terminal window. Python of generate.py, Enter. And it looks like the first coin toss was the heads. Let's go ahead and run it again.

S1

Speaker 1

04:58:45

And it looks like it was heads again. Maybe you want to chime into the chat here. If I run it a third time, what's it going to be this time? If you want to type your thoughts in the chat, you might think there's a bug here.

S1

Speaker 1

04:58:56

But this is probability in action. If I go ahead and hit Enter a third time, there, it's actually now tails. And again, tails. And again, tails.

S1

Speaker 1

04:59:05

And again, tails. And again, tails. And again, heads. Now, if we did this an infinite number of times, it would indeed work out to be 50-50.

S1

Speaker 1

04:59:12

If we only do it a few times, it might not work out as cleanly. But that's how probabilities indeed work. All right, so I've got that now working. Could I have implemented this in a different way?

S1

Speaker 1

04:59:22

Well, let me show you an alternative to actually using the import keyword alone. And let me introduce the keyword from in Python. So from is a keyword in Python that you can use when importing functions from a module, but it allows you to be a little more specific than import alone. So if I go back to my code here, it's worth noting that what technically I'm doing here by importing random is I'm technically importing everything that's in that module.

S1

Speaker 1

04:59:50

So not just the function called random.choice, but a few other functions as well. So instead of using this line of code at the top of my file, import random, which will technically give me everything.