CS50 Video Player
    • 🧁

    • 🍮

    • 🍉

    • 🍿
    • 0:00:00Introduction
    • 0:01:12Python
    • 0:03:10Compilation, Interpretation
    • 0:04:32Hello
    • 0:15:09Types
    • 0:16:51Speller
    • 0:25:56Image Recognition
    • 0:31:06CS50 library
    • 0:32:22Conditionals
    • 0:35:09Variables
    • 0:36:33Loops
    • 0:41:50Calculator
    • 0:51:35Compare
    • 0:59:31Object-Oriented Programming
    • 1:05:20Meow
    • 1:14:38Mario
    • 1:35:45Scores
    • 1:40:35Uppercase
    • 1:43:57Greet
    • 1:48:27Exit Status
    • 1:51:02Search
    • 1:54:15Phonebook
    • 2:00:49Compare
    • 2:04:11Swap
    • 2:05:13CSV
    • 2:11:01Speech
    • 0:00:02[MUSIC PLAYING]
    • 0:01:12DAVID MALAN: All right.
    • 0:01:13This is CS50, and this is week six, wherein we finally transition
    • 0:01:18from Scratch to C to, now, Python.
    • 0:01:20And, indeed, this is going to be somewhat
    • 0:01:22of a unique experience in that, just like a few weeks past--
    • 0:01:27perhaps, for the first time-- and now, today, you're
    • 0:01:30going to learn a new language.
    • 0:01:31But the goal isn't just to throw another fire hose of content and syntax
    • 0:01:35and whatnot at you, but rather, to really equip you all to actually teach
    • 0:01:39yourself new languages in the future.
    • 0:01:41And so, indeed, what we'll do today, what we'll do this coming week
    • 0:01:43is prepare you to stand on your own.
    • 0:01:46And once Python is passe and the world has
    • 0:01:48moved on to some other language in some number of years,
    • 0:01:50you'll be well equipped to figure out how
    • 0:01:52to wrap your mind around some new syntax, some new language
    • 0:01:55and solve problems, as well.
    • 0:01:56Now, you recall, in week zero, this is where we started--
    • 0:01:59just saying hello to the world.
    • 0:02:01And that quickly escalated just a week later in C
    • 0:02:03to be something much, much more cryptic.
    • 0:02:06And if you've still struggled with some of the syntax,
    • 0:02:09find yourself checking your notes or your previous code,
    • 0:02:11that's totally normal.
    • 0:02:12And that's one of the reasons why there are languages besides C
    • 0:02:16out there-- among them, this language called Python.
    • 0:02:18Humans over the decades have realized, gee,
    • 0:02:21that wasn't necessarily the best design decision, or humans have realized, wow,
    • 0:02:25you know what?
    • 0:02:25Now that computers have gotten faster with more memory and faster CPUs,
    • 0:02:30we can actually do more with our programming languages.
    • 0:02:33So just as human languages evolve, so do actual programming languages.
    • 0:02:36And even within a programming language, there's typically different versions.
    • 0:02:40We, for instance, have been using version C11
    • 0:02:43of C, which was updated in 2011.
    • 0:02:46But Python itself continues to evolve, and it's now up to version 3-plus.
    • 0:02:50And so there, too, these things will evolve in the coming days.
    • 0:02:53Thankfully, what you're about to see is "Hello, World!"
    • 0:02:56for the third time, but it's going to be literally this.
    • 0:02:59None of the crazy syntax above or below, fewer semicolons, if any, fewer
    • 0:03:04currently braces.
    • 0:03:05And, really, a lot of the distractions get out of the way.
    • 0:03:08So to get there, let's consider exactly how
    • 0:03:11we've been programming up until now.
    • 0:03:13So you write a program in C and you've got, hopefully,
    • 0:03:16no syntax error, so you're ready to build it-- that is, compile it.
    • 0:03:19And so, you've run make, and then, you've run the program, like ./hello.
    • 0:03:22Or if you think back to week two, where we
    • 0:03:24took a peek underneath the hood of what make is doing,
    • 0:03:27it's really running the actual compiler--
    • 0:03:29something called clang-- maybe with some command-line arguments creating
    • 0:03:32a program called hello.
    • 0:03:34And then, you could do ./hello.
    • 0:03:36So, today, you're going to start doing something similar in spirit,
    • 0:03:38but fewer steps.
    • 0:03:40No longer will you have to compile your code
    • 0:03:42and then run it, and then, maybe, fix or change it, and then compile your code
    • 0:03:45and run it, and then repeat, repeat.
    • 0:03:47The process of running your code is going
    • 0:03:50to be distilled into just a single step.
    • 0:03:52And the way to think of this, for now, is
    • 0:03:54that, whereas C is frequently used as, indeed, a compiled language whereby
    • 0:03:58you convert it first to 0s and 1s, Python's
    • 0:04:01going to let you speed things up whereby you, the human programmer,
    • 0:04:04don't have to compile it.
    • 0:04:05You're just going to run what's called an interpreter-- which, by design,
    • 0:04:09is named the exact same thing as the language itself--
    • 0:04:12and by running this program installed in VS Code
    • 0:04:14or, eventually, on your own Macs or PCs.
    • 0:04:17This is just going to tell your computer to interpret this code
    • 0:04:20and figure out how to get down to that lower level of 0s and 1s.
    • 0:04:23But you don't have to compile the code yourself anymore.
    • 0:04:26So with that said, let's consider what the code is going to look like,
    • 0:04:31side by side.
    • 0:04:31In fact, let's look back at some Scratch blocks,
    • 0:04:33just like we did with C in week one, and do some side by sides.
    • 0:04:36Because even though some of the syntax this week and beyond
    • 0:04:39is going to be different, the ideas are truly going to be the same.
    • 0:04:42There's not all that much intellectually new just yet.
    • 0:04:45So whereas, in week zero, we might have said hello to the world
    • 0:04:48with this purple puzzle piece, today, of course--
    • 0:04:51or, rather, in week one, it looked like this in C. But today, moving forward,
    • 0:04:56it's going to, quite simply, look like this instead.
    • 0:04:58And if we go back and forth for just a moment,
    • 0:05:00here, again, is the version in C, noticing
    • 0:05:03the very C-like characteristics.
    • 0:05:05And just at a glance here, in Python, I claim it's now this.
    • 0:05:09What do you apparently need not worry about anymore?
    • 0:05:13What's gone?
    • 0:05:14So semi-colon is gone.
    • 0:05:15And, indeed, you don't need those to finish most of your thoughts anymore.
    • 0:05:19Anything else?
    • 0:05:19AUDIENCE: Backslash n.
    • 0:05:20DAVID MALAN: So the backslash n is absent.
    • 0:05:22And that's curious because we're still going to get a new line,
    • 0:05:25but we'll see that it's become the default.
    • 0:05:26And this one's a little more subtle, but now, the function
    • 0:05:29is called print instead of printf.
    • 0:05:31So it's a little more familiar in that sense.
    • 0:05:33All right.
    • 0:05:34So when it comes to using libraries-- that
    • 0:05:37is, code that other people have written-- in the past,
    • 0:05:39we've done things like #include cs50.h to use CS50's own header
    • 0:05:43file or standard I/O or standard lib or string or any number of other header
    • 0:05:47files you have all used.
    • 0:05:49Moving forward, we're going to give you, for this first week, a similar CS50
    • 0:05:52library--
    • 0:05:53just very short-term training wheels that we'll quickly
    • 0:05:55take off because, in reality, it's a lot easier to do things in Python,
    • 0:05:59as we'll see.
    • 0:06:00But the syntax for this, now, is going to be
    • 0:06:02to import the CS50 library in this way.
    • 0:06:05And when we have, now, this ability, we can actually
    • 0:06:08start writing some code right away.
    • 0:06:09In fact, let me switch over to VS Code here.
    • 0:06:12And just as in the past, I'll create a new file.
    • 0:06:14But instead of creating something called .c,
    • 0:06:17I'm going to go ahead and create my first program called hello.py,
    • 0:06:19using code space hello dot py.
    • 0:06:22That, of course, gives me this new tab.
    • 0:06:24And let me actually, quite simply, do what I proposed-- print, quote unquote,
    • 0:06:28"Hello, world" without the /n, without the semicolon, without the f in print.
    • 0:06:33And now, let me go down to my terminal window.
    • 0:06:36And I don't have to compile it.
    • 0:06:37I don't have to do dot slash.
    • 0:06:39I, instead, run a program called python, whose purpose in life
    • 0:06:43is, now, to interpret my code top to bottom, left to right.
    • 0:06:46And if I run python of hello.py, crossing my fingers, as always--
    • 0:06:50voila.
    • 0:06:51Now I have printed out "hello, world."
    • 0:06:53So we seem to have gotten the new line for free, in the sense where
    • 0:06:56it's automatically happening.
    • 0:06:57The dollar sign isn't weirdly on the same line,
    • 0:06:59like it once was in week one.
    • 0:07:02But that's just a minor detail here.
    • 0:07:04If we switch back to, now, some other capabilities--
    • 0:07:06well, indeed, with the CS50 library, you can also not
    • 0:07:09just import the library itself, but specific functions.
    • 0:07:12And you'll see that, temporarily, we're going
    • 0:07:14to give you a helper function called get_string, just like in C, that just
    • 0:07:19makes it work exactly the same way as in C.
    • 0:07:20And we'll see a couple of other functions
    • 0:07:22that will just make life easier, initially.
    • 0:07:24But, quickly, will we take those training wheels off
    • 0:07:26so that nothing is, indeed, CS50-specific.
    • 0:07:29All right.
    • 0:07:29Well, how about functions, more generally, in Python?
    • 0:07:32Let's do a whirlwind tour, if you will, much
    • 0:07:34like we did in that first week of C, comparing one to the other.
    • 0:07:38So back in our world of Scratch, one of the first programs we wrote
    • 0:07:42was this one here, whereby we ask the human their name.
    • 0:07:45We then used the return value that was automatically stored
    • 0:07:49in this answer variable as an second argument
    • 0:07:53to join so that we could say "Hello, David" or "Hello, Carter."
    • 0:07:56So this was back in week zero.
    • 0:07:59In week one, we converted it to this.
    • 0:08:01And here is a perfect example of things like escalating quickly.
    • 0:08:03And, again, this is why we start in Scratch.
    • 0:08:05There's just so much distraction here to achieve the same idea.
    • 0:08:09But even today, we're going to chip away at some of that syntax.
    • 0:08:12So, in C, we had to declare the variable as a string, here.
    • 0:08:17We of course, had the semicolon and more.
    • 0:08:19Well, in Python, the comparable code, now,
    • 0:08:22is going to look, more simply, like this.
    • 0:08:26So semicolon is, again, gone on both lines, for that matter.
    • 0:08:29So that's good.
    • 0:08:30What else appears to have changed or disappeared?
    • 0:08:33Yeah.
    • 0:08:33AUDIENCE: [? Do you have ?] the same type of variable?
    • 0:08:35DAVID MALAN: Yeah.
    • 0:08:36So I didn't have to specifically say that answer is now a string.
    • 0:08:39And, indeed, Python is dynamically typed.
    • 0:08:41And, in fact, it will infer from context exactly what
    • 0:08:45it is you are storing in that variable.
    • 0:08:48Other details that seem a little bit different?
    • 0:08:53A little bit different.
    • 0:08:54What else jumps out at you here?
    • 0:08:55I'll go back.
    • 0:08:56This was the C version.
    • 0:08:58And maybe focus, now, on the second line because we've rather
    • 0:09:01exhausted the first.
    • 0:09:02Here's, now, the Python version.
    • 0:09:04What's different here?
    • 0:09:05Yeah?
    • 0:09:06AUDIENCE: You don't need to worry about %s or percent anything.
    • 0:09:08You just have the variable after [? them. ?]
    • 0:09:10DAVID MALAN: Yeah.
    • 0:09:11There's no %s anymore.
    • 0:09:12There's no second argument, at the moment, per se, to print.
    • 0:09:16Now, it is still a little weird.
    • 0:09:17It's as though I've deployed some addition here, arithmetically.
    • 0:09:20But that's not the case.
    • 0:09:21Some of you have program before.
    • 0:09:23And plus, some of you might know, means what in this context?
    • 0:09:27So to combine or, more technically-- anyone know the buzzword?
    • 0:09:29Yeah.
    • 0:09:30AUDIENCE: Concatenate.
    • 0:09:31DAVID MALAN: To concatenate.
    • 0:09:32So to concatenate is the fancy way of what Scratch calls joining,
    • 0:09:35which is to take one string on the left, one string on the right
    • 0:09:38and to join them together.
    • 0:09:40To glue them together, if you will.
    • 0:09:41So this is not addition.
    • 0:09:43It would be if it were numbers involved instead.
    • 0:09:45But because we've got a string--
    • 0:09:46Hello comma-- and another string implicitly in this variable
    • 0:09:49based on what the human typed in in response to this get_string function.
    • 0:09:53That's going to concatenate Hello comma space, and then, David or Carter
    • 0:09:58or whatever the human has typed in.
    • 0:09:59But it turns out, there's going to be different ways to do this in Python.
    • 0:10:02And we'll show you a few different ones.
    • 0:10:04And here, too, try not to get too hung up
    • 0:10:06on or frustrated by all of the different ways you can solve problems.
    • 0:10:09Odds are, you're going to be picking up tips and techniques for years
    • 0:10:12to come if you continue programming.
    • 0:10:14So let's just give you a few of the possible ways.
    • 0:10:16So here's a second way you could print out hello comma David or hello comma
    • 0:10:20Carter.
    • 0:10:21But what has changed?
    • 0:10:22In the previous version, I used concatenation explicitly.
    • 0:10:26And the space here is important, grammatically,
    • 0:10:28just so we get that in the final phrase.
    • 0:10:30Now, I'm proposing to get rid of that space
    • 0:10:33to add a comma outside of the double quotes, as well.
    • 0:10:36But if you think back to C, this probably
    • 0:10:39just means that print, similar in spirit to printf,
    • 0:10:42can take not just one argument, but even two.
    • 0:10:45And in fact, because of this comma in the middle that's
    • 0:10:47outside of the double quotes, it's hello comma,
    • 0:10:50and then, it will be automatically concatenated
    • 0:10:52with-- even without using the plus, to whatever the value of answer is.
    • 0:10:56And by default, just for grammatical prettiness,
    • 0:10:59the print function always gives you a space
    • 0:11:01for free in between each of the multiple arguments you pass in.
    • 0:11:05We'll see how you can override that down the line.
    • 0:11:07But, for now, that's just another way to do it.
    • 0:11:09Now, perhaps the better, if slightly cryptic way to do this--
    • 0:11:12or just the increasingly common way--
    • 0:11:14is, probably, the third version, which looks a little weird, too.
    • 0:11:18And, probably, the weirdness jumps out.
    • 0:11:20We've suddenly introduced these curly braces,
    • 0:11:24which I promised were mostly gone.
    • 0:11:25And they are.
    • 0:11:26But inside of this string here, I've done
    • 0:11:29a curly brace, which might mean what?
    • 0:11:31Just intuitively.
    • 0:11:32And here is an example of how you learn a new language.
    • 0:11:35Just infer, from context, how Python probably works.
    • 0:11:39What might this mean?
    • 0:11:40Yeah?
    • 0:11:41AUDIENCE: [INAUDIBLE]
    • 0:11:45DAVID MALAN: Yeah.
    • 0:11:45So this is an indication, because the curly braces--
    • 0:11:48because this was the way Python was designed--
    • 0:11:50that we want to plug in the value of answer, not literally A-N-S-W-E-R.
    • 0:11:55And the fancy word here is that the answer variable will be interpolated--
    • 0:11:59that is, substituted with its actual value.
    • 0:12:01But, but, but-- and this is actually weird-looking;
    • 0:12:04this was introduced a few years ago to Python.
    • 0:12:06What else did I have to change to make these curly braces work, apparently?
    • 0:12:11Yeah?
    • 0:12:11AUDIENCE: Drop the f before the--
    • 0:12:13DAVID MALAN: Yeah.
    • 0:12:14There's this weird f.
    • 0:12:15And so, it's like part of printf.
    • 0:12:17But now, it's inside the parentheses there.
    • 0:12:20This is just the way Python designed this.
    • 0:12:22So a few years ago, when they introduced what
    • 0:12:24are called format strings or fstrings, you literally prefix your quoted string
    • 0:12:30with the letter f.
    • 0:12:32And then, you can use trickery like this,
    • 0:12:34like putting curly braces so that the value will
    • 0:12:36be substituted automatically.
    • 0:12:38If you forget the f, you're going to literally see hello comma curly
    • 0:12:41brace answer closed curly brace.
    • 0:12:43If you add the f, it's, indeed, interpolated.
    • 0:12:45The value is plugged in.
    • 0:12:47All right.
    • 0:12:47Questions on how we can just say hello to the world via Python, in this case.
    • 0:12:52Yeah?
    • 0:12:53AUDIENCE: If you do this without the f, what would happen?
    • 0:12:55DAVID MALAN: If you do this without the--
    • 0:12:56AUDIENCE: [? The f. ?]
    • 0:12:57DAVID MALAN: Without the f?
    • 0:12:58If you omit the f, you will literally see H-E-L-L-O comma curly brace
    • 0:13:02A-N-S-W-E-R closed curly brace.
    • 0:13:04So, in fact, let's do this.
    • 0:13:05Let me go back to VS Code here, quickly.
    • 0:13:08I've still got my file called hello.py open.
    • 0:13:11And let me go ahead and change this ever so slightly.
    • 0:13:14So I'm going to go ahead and--
    • 0:13:16let's say from cs50 import get_string.
    • 0:13:20And that's just the new syntax I propose using to import
    • 0:13:23a function from someone else's library.
    • 0:13:26I'm going to now go ahead and ask the question--
    • 0:13:30let's go ahead and use get_string, storing the result in answer.
    • 0:13:33So get_string, quote unquote, "What's your name?"
    • 0:13:37And then, on this line, I'm going to deliberately make a mistake here,
    • 0:13:41exactly to your question.
    • 0:13:42Let me just say hello comma answer, and just this.
    • 0:13:46Now, even though answer is a variable, Python's
    • 0:13:48not going to be so presumptuous as to just plug in the value of a variable
    • 0:13:53called answer.
    • 0:13:53What it's going to do, of course, is--
    • 0:13:56if I type in my name--
    • 0:13:56whoops.
    • 0:13:57I typed too fast.
    • 0:13:58Let me go ahead and rerun that again.
    • 0:14:00If I run python with hello.py, type in my name and hit Enter,
    • 0:14:04I get hello comma answer.
    • 0:14:06Well, let me do one better.
    • 0:14:07Let me apply these curly braces as before.
    • 0:14:10Let me rerun python of hello.py.
    • 0:14:13What's your name?
    • 0:14:14D-A-V-I-D.
    • 0:14:14And here's, again, the answer to your question.
    • 0:14:16Now, we get, literally, the curly braces.
    • 0:14:18So the fix here, ultimately, is just going
    • 0:14:20to be to add the f there, rerun my program again with David.
    • 0:14:24And now, hello comma David.
    • 0:14:26So this is, admittedly, a little more cryptic than the ones
    • 0:14:28with the plus or the comma, but this is just increasingly common.
    • 0:14:31Why? because you can read it left to right.
    • 0:14:33It's nice and convenient.
    • 0:14:34It's less cryptic than the %s's.
    • 0:14:36So it's a new and improved version, if you will, of printf in C,
    • 0:14:40based on decades of experience of programmers doing things like this.
    • 0:14:44Questions on printing in this way?
    • 0:14:49We're now on our way to programming in Python.
    • 0:14:52Anything?
    • 0:14:53All right.
    • 0:14:53Well, what more can we do with this language, here?
    • 0:14:56Well, let me propose that we consider that we
    • 0:15:00have, for instance, a few other features that we can add to the mix, as well--
    • 0:15:07namely, let's say some data types, as well.
    • 0:15:12So let me flip over here, to back to the slides.
    • 0:15:15And there's different data types in Python, as we'll soon see.
    • 0:15:18But they're not as explicit.
    • 0:15:19As we already saw, by using a string from get_string,
    • 0:15:23you don't have to explicitly state what it is.
    • 0:15:25But you saw-- recall, in C-- all of these various data types.
    • 0:15:29And then, in Python, nicely enough, this list is about to get shorter.
    • 0:15:33And so, here is our list in C. Here is an abbreviated list in Python.
    • 0:15:37So we're still going to have strings, but they're going to be more succinctly
    • 0:15:41called strs now, S-T-R. We're still going to have ints for integers.
    • 0:15:45We're still going to have floats for floating point values.
    • 0:15:47We're even going to have bools for true and false.
    • 0:15:49But what's missing, now, from the list is long and floats.
    • 0:15:53And why is that?
    • 0:15:54Or rather, long and double.
    • 0:15:56We'll recall that, in C, those used more bits.
    • 0:15:58Well, in Python, the smaller data types, previously-- int and float,
    • 0:16:02themselves-- just used more bits for you.
    • 0:16:04And so, you don't need to distinguish between small and large.
    • 0:16:08You just use one data type, and the language
    • 0:16:10gives you a bigger range than before.
    • 0:16:12It turns out, though, there's going to be some other features, as well,
    • 0:16:15of Python, and these data types-- one of which
    • 0:16:17will be called range, another of which will be list.
    • 0:16:20So gone will be arrays.
    • 0:16:21We'll actually use something literally called a list.
    • 0:16:23Tuples-- sort of x, y pairs for coordinates and things like that.
    • 0:16:28Dicts for dictionaries-- so we'll have built-in capabilities
    • 0:16:31for storing keys and values we'll see, and even a set.
    • 0:16:34Mathematically, a set is a collection of values,
    • 0:16:36but it automatically gets rid of duplicates for you.
    • 0:16:38So all of these things, we could absolutely implement in C if we wanted.
    • 0:16:43And, indeed, in problem set five, you've been implementing your very own spell
    • 0:16:47checker using some form of hash table.
    • 0:16:50Well, it turns out that, in Python, you can solve those same problems,
    • 0:16:54but perhaps a little more readily.
    • 0:16:56In fact, let me go back over here to VS Code,
    • 0:16:58and let me propose that I do the following.
    • 0:17:01Let me go ahead and create a file called dictionary.py.
    • 0:17:06Let me propose that I try to implement, say-- problem set five--
    • 0:17:09our spell checker in Python instead of C and achieve, ultimately,
    • 0:17:14the same kind of behavior whereby I'll be
    • 0:17:17able to spell check a whole bunch of words.
    • 0:17:19So this is jumping the gun a little bit because you're
    • 0:17:21about to see syntax will revisit over the course of today.
    • 0:17:23But, for now, I've got a new file called dictionary.py.
    • 0:17:26And let me begin to create some placeholders for functions.
    • 0:17:30We'll see in just a bit that, in Python, you can define a function called check,
    • 0:17:34and that check function can take a word as its input.
    • 0:17:38And I'll come back to this in just a moment.
    • 0:17:40In Python, I can define a second function
    • 0:17:42like load, which itself will take a whole dictionary,
    • 0:17:44just like in problem set five.
    • 0:17:47And I'll go ahead and come back to the implementation of this.
    • 0:17:51Meanwhile, we might similarly implement a function
    • 0:17:53called size, which takes no arguments but, ultimately, is going to return
    • 0:17:57the size of my dictionary of words.
    • 0:17:59And then, lastly, for consistency with problem set five,
    • 0:18:02we might define an unload function, whose purpose in life
    • 0:18:05is to free any memory that you've been using, just
    • 0:18:07to give it back to the computer.
    • 0:18:09Now, odds are, whether you're still working on speller
    • 0:18:11or have finished speller, you wrote a decent amount of lines of code.
    • 0:18:15And indeed, it's been, by design, a challenge.
    • 0:18:18But one of the reasons for these higher-level languages like Python
    • 0:18:22is that you can stand on the shoulders of programmers before you
    • 0:18:25and solve very common problems much more quickly.
    • 0:18:28So that you can focus on building your new app or your web application
    • 0:18:31or your own project to solve problems of interest to you.
    • 0:18:34So at the risk of crushing some spirits, let
    • 0:18:38me propose that, in Python if you want a dictionary for something like a spell
    • 0:18:42checker, well, that's fine.
    • 0:18:44Go ahead and give yourself a variable, like words, to store all of those words
    • 0:18:48and just assign it equal to a dictionary-- or dict, for short,
    • 0:18:52in Python.
    • 0:18:53That will give you a hash table.
    • 0:18:55Now, it turns out, in speller recall, you
    • 0:18:57don't need to worry about words and definitions.
    • 0:18:59It's just about spell-checking the words.
    • 0:19:01So strictly speaking, we don't need keys and values.
    • 0:19:03We just need keys.
    • 0:19:05So I'm going to save myself a few more keystrokes
    • 0:19:07by just saying that, technically, in Python, using a set suffices.
    • 0:19:11Again, a set is just a collection of values with no duplicates.
    • 0:19:13But they don't necessarily have keys and values.
    • 0:19:16It's just one or the other.
    • 0:19:18But now that I have-- on line one, I claim the equivalent, in Python,
    • 0:19:21of a hash table, I can actually do something like this.
    • 0:19:25Here's how I might implement the check function in Python.
    • 0:19:28If the word passed into this function is in my variable called words,
    • 0:19:33well, return True.
    • 0:19:35Else, go ahead and return False.
    • 0:19:39Done.
    • 0:19:40No, wait.
    • 0:19:40You're thinking, if anything at all, maybe
    • 0:19:42we want to handle lowercase instead of just uppercase and lowercase.
    • 0:19:46Well, you know what?
    • 0:19:47In Python, if you want to force a whole word to lowercase,
    • 0:19:49you don't have to iterate over it with a loop.
    • 0:19:51You don't have to use any of that C-type functions or anything.
    • 0:19:54Just say word.lower, and that will convert the whole thing
    • 0:19:56to lowercase for parity with the dictionary.
    • 0:19:58All right.
    • 0:19:59How about something like the load function in Python?
    • 0:20:02Well, in Python, you can open files just like in C. For instance, in Python, I
    • 0:20:06might do open, the dictionary argument in read mode,
    • 0:20:09just like fopen in Python.
    • 0:20:11I might do something like this.
    • 0:20:13For each line in that file, let me go ahead and add, to my words variable,
    • 0:20:20that line.
    • 0:20:21And then, let me go ahead and close that file.
    • 0:20:24And I think I'm done.
    • 0:20:26I'm just going to go ahead and return True,
    • 0:20:28just because I think I'm already done.
    • 0:20:30Now, here, too, I could nitpick a little bit.
    • 0:20:32Technically, if I'm reading in every line from the file,
    • 0:20:35every line in the dictionary ends with, technically, a backslash n.
    • 0:20:38But there's an easy way to get rid of that,
    • 0:20:41just like you might see with an alternative syntax.
    • 0:20:43What I'm actually going to do is this.
    • 0:20:45Let me grab from the current line, the current word,
    • 0:20:49by stripping off with reverse strip--
    • 0:20:51rstrip; a function we'll, again, see--
    • 0:20:53that just gets rid of the trailing new line--
    • 0:20:55the backslash n at the end of that line.
    • 0:20:58And what I really want to do, then, is add this word to that dictionary.
    • 0:21:01Meanwhile, if I want to figure out what the size is of my dictionary, well--
    • 0:21:05and, see, you're probably writing code to iterate over all of those lines,
    • 0:21:08and you're just going to count them up using a variable.
    • 0:21:12Not so in Python.
    • 0:21:13You can just return the length of those words.
    • 0:21:15And better still, in Python, you don't have to manage your own memory.
    • 0:21:19No more malloc.
    • 0:21:20No more free.
    • 0:21:21No more manual thinking about memory.
    • 0:21:24The language just deals with all of that for you.
    • 0:21:27So you know what?
    • 0:21:28It suffices for me to just return True and claim
    • 0:21:30that unloading is done for me.
    • 0:21:33And that's it.
    • 0:21:35Again, whether, you're in the middle of or already finished,
    • 0:21:37this might, perhaps, adjust some frustration,
    • 0:21:39but also, enlightenment in that this is why higher-level languages exist.
    • 0:21:45You can build on top of the same principles,
    • 0:21:47the same ideas, with which you've been dealing,
    • 0:21:50struggling even this past week.
    • 0:21:51But you can now express yourself all the more succinctly.
    • 0:21:55This one line implements a hash table for you, and all of this, now,
    • 0:21:59just uses that hash table in a simpler way.
    • 0:22:03Any questions, now, on this, keeping in mind
    • 0:22:05that the point, nonetheless, of speller in p-set 5
    • 0:22:08is to understand what's really going on underneath the hood
    • 0:22:12and, better still, to notice this.
    • 0:22:14This might seem all rather amazing, but let me go ahead and do this.
    • 0:22:18I've actually got a couple of versions of speller written here,
    • 0:22:21and I've got a version written in C that I won't show the source code for.
    • 0:22:24But I'm going to go ahead and make that version of speller in C.
    • 0:22:28And I'm going to go ahead here and, let's say, split
    • 0:22:32my window here for just a moment.
    • 0:22:34And I'm going to go into a Python version of speller,
    • 0:22:37really, that I just wrote.
    • 0:22:38And on the left-hand side here, let me go ahead and run speller--
    • 0:22:42the version I compiled in C--
    • 0:22:44using a big text like the Sherlock Holmes text,
    • 0:22:47which has a whole lot of words in it.
    • 0:22:50And on the right-hand side, let me run python
    • 0:22:52of speller.py, which is a separate file I wrote in advance,
    • 0:22:55just like we give you speller.c.
    • 0:22:57And I'll, similarly, run this on the Sherlock Holmes text.
    • 0:23:00And I'm going to do my best to hit Enter on the left and the right of my screen
    • 0:23:05at the same time.
    • 0:23:06But we should see, hopefully, the same list of misspelled words
    • 0:23:08and the timings thereof.
    • 0:23:10So here we go on the right.
    • 0:23:12Here we go on the left.
    • 0:23:15All right.
    • 0:23:16A race to see which one wins here.
    • 0:23:18C is on the left.
    • 0:23:19Python is on the right.
    • 0:23:21OK.
    • 0:23:23Interesting.
    • 0:23:25Hopefully, Python's close behind.
    • 0:23:28Note that some of this is internet delay.
    • 0:23:30And so, it might not necessarily be a crazy number of seconds.
    • 0:23:33But the system is, indeed, using, if we measure it, a low level.
    • 0:23:37How much time the CPU spent executing my code?
    • 0:23:39C took a total of 1.64 seconds.
    • 0:23:41That was pretty fast, even though it took a moment more for all of the bytes
    • 0:23:44to come over the internet.
    • 0:23:46The Python version, though, took what?
    • 0:23:492.44 seconds.
    • 0:23:50So what might the inference be?
    • 0:23:53One, maybe I'm just better at programming in C
    • 0:23:55than I am in Python, which is probably not true.
    • 0:23:59But what else might you infer from this example?
    • 0:24:07Should we, maybe, give up on Python, stick with C?
    • 0:24:11No?
    • 0:24:12So what might be going on here?
    • 0:24:14Why is the Python version, that I claim is correct--
    • 0:24:16and I think the numbers all line up, just not the times.
    • 0:24:20Where is the trade-off here?
    • 0:24:21Well, here, again, is this design trade-off.
    • 0:24:23Yeah?
    • 0:24:24AUDIENCE: In order to save the programmer time, [INAUDIBLE]..
    • 0:24:29DAVID MALAN: Yeah, exactly.
    • 0:24:30In order to save the human programmer time,
    • 0:24:32there's a lot more features built into Python-- more functions,
    • 0:24:35more automatic management of memory and so forth--
    • 0:24:38and you have to pay a price.
    • 0:24:40Someone else's code is doing all of that work for you.
    • 0:24:43But if they've written some number of lines of code,
    • 0:24:45those are just more lines of code that need
    • 0:24:47to be executed for you, whereas here, the computer is
    • 0:24:50at the risk of oversimplifying only running my lines of code.
    • 0:24:54So there's just less overhead.
    • 0:24:55And so, this is a perpetual trade-off.
    • 0:24:57Typically, when using a more user-friendly and more modern language,
    • 0:25:00one of the prices you might pay is performance.
    • 0:25:02Now, there's a lot of smart computer scientists in the world, though, trying
    • 0:25:06to push back on those same trade-offs.
    • 0:25:08And so, these interpreters, like the command I wrote,
    • 0:25:11Python technically can-- especially if you run a program again and again--
    • 0:25:15actually, secretly, behind the scenes, compile your code for you,
    • 0:25:19down to 0s and 1s.
    • 0:25:20And then, the second, the third, the fourth time you run that program,
    • 0:25:23it might very well be faster.
    • 0:25:25So this is a bit of a head fake here, in that
    • 0:25:27I'm running them once and only once.
    • 0:25:29But we could get benefit over time if we kept
    • 0:25:32running the Python version again and again
    • 0:25:34and, perhaps, fine-tune the performance.
    • 0:25:35But, in general, there's going to be this trade-off.
    • 0:25:38Now, would you rather spend the 60 seconds
    • 0:25:40I wrote implementing a spell checker or this 6 hours,
    • 0:25:4316 hours you might be or have spent implementing the same in C?
    • 0:25:47Probably not.
    • 0:25:48For productivity's sake, this is why we have these additional languages.
    • 0:25:52Just for fun, let me flip over to another screen here and open up
    • 0:25:57a version of Python that's actually-- in just a second--
    • 0:26:00on my own Mac instead of the cloud so that
    • 0:26:04I can actually do something with graphics.
    • 0:26:06So, here, I just have a black and white terminal window on my very own Mac.
    • 0:26:09And I've pre-installed Python, just like we've done so
    • 0:26:12for VS Code in the cloud for you.
    • 0:26:14Notice that I've got this photo of, perhaps, one of your favorite TV
    • 0:26:19shows here, with the cast of The Office.
    • 0:26:21Notice all of the faces in this image here.
    • 0:26:24And let me propose that we try to find one face in the crowd, CSI-style,
    • 0:26:30whereby we want to find, perhaps, the Scranton Strangler, so to speak.
    • 0:26:33And so, here is an example of this guy's face.
    • 0:26:37Now, how do we go about finding this specific face in the crowd?
    • 0:26:40Well, our human eyes, obviously, can pluck him out,
    • 0:26:42especially if you're familiar with the show.
    • 0:26:44But let me go ahead and do this instead.
    • 0:26:46Let me go ahead and propose that we run code
    • 0:26:50that I already wrote in advance here.
    • 0:26:52This is a Python program with more lines of code
    • 0:26:55that we won't dwell on for today.
    • 0:26:56But it's meant to motivate what we can do.
    • 0:26:58From a pillow library, implying a Python image library,
    • 0:27:03I want to import some type of information,
    • 0:27:07some feature called image so that I can manipulate images,
    • 0:27:09not unlike our own problem set four.
    • 0:27:12And this is powerful.
    • 0:27:13in?
    • 0:27:13Python.
    • 0:27:14You can just [MIMICS EXPLOSION] import face recognition as a library
    • 0:27:18that someone else wrote.
    • 0:27:19From there, I'm going to create a variable called image.
    • 0:27:22I'm going to use this face recognition libraries.
    • 0:27:25load_image_file function.
    • 0:27:27It's a little verbose, but it's similar in spirit to fopen.
    • 0:27:30And I'm going to open office.jpeg.
    • 0:27:32I'm going to, then, declare a second variable called face_locations, plural,
    • 0:27:36because what I'm expecting to get back, per the documentation for this library,
    • 0:27:40is a list of all of the faces' locations that are detected.
    • 0:27:44All right.
    • 0:27:45Then, I'm going to iterate over each of those faces using a for loop,
    • 0:27:48that we'll see in more detail.
    • 0:27:50I'm going to, then, infer what the top, right, bottom, and left corners
    • 0:27:53are of that face.
    • 0:27:55And then, what I'm going to do here is show that face alone,
    • 0:28:00if I've detected the face in question.
    • 0:28:03So let me go ahead, here, and run detect.py.
    • 0:28:08And we'll see not just the one face we're looking for.
    • 0:28:12But if I run Python of detect.py, it's going to do all of the analysis.
    • 0:28:16I'll see a big opening here, now, of all of the faces that
    • 0:28:22were detected in this here program.
    • 0:28:24[CHUCKLES] OK, some better than others, I guess,
    • 0:28:26if you zoom in on catching someone.
    • 0:28:28Typical Angela.
    • 0:28:29If you want to, now, find that one face, I
    • 0:28:32think we need to train the software a bit more.
    • 0:28:34So let me actually open up a second program called
    • 0:28:37recognize that's got more going on.
    • 0:28:39But let me, with a wave of a hand, point out
    • 0:28:41that I'm now loading not only the office.jpeg, but also toby.jpeg
    • 0:28:45to train the algorithm to find that specific face.
    • 0:28:49And so, now, if I run this second version-- recognize.py--
    • 0:28:53with Python of recognize.py--
    • 0:28:56hold my breath for just a moment; it's analyzing, presumably,
    • 0:28:59all of the faces--
    • 0:29:00you see the same, original photo.
    • 0:29:02But do you see one such face highlighted here?
    • 0:29:05This version of the code found Toby, highlighted him
    • 0:29:09with the screen and, voila, we have face recognition.
    • 0:29:12So for better or for worse, this is what's happening,
    • 0:29:14increasingly societally, nowadays.
    • 0:29:15And honestly, even though I didn't write the code live--
    • 0:29:18because it's a good dozen or more lines of code-- it's not terribly many.
    • 0:29:21And literally, all the authorities-- all we have to do
    • 0:29:24is import face recognition and, voila, you have access.
    • 0:29:27These technologies are here already.
    • 0:29:29But let's consider, for just a moment--
    • 0:29:31how did we find Toby?
    • 0:29:33How might that library--
    • 0:29:35even though we're not going to look at its implementation details,
    • 0:29:37how does it find Toby and distinguish him
    • 0:29:40from all of these other faces in the crowd?
    • 0:29:43What might it be doing, intuitively.
    • 0:29:47Think back even to p-set four, what you, yourselves, have access to, data-wise.
    • 0:29:50Yeah?
    • 0:29:51AUDIENCE: [? Since ?] we gave it an image of Toby's face before,
    • 0:29:53it probably looks at are the pixels in one area the same as in another area
    • 0:29:59and allots it to the same--
    • 0:30:00from that reference image to this image.
    • 0:30:02And then, it's going to say, hey, a lot of the similar consult ranges
    • 0:30:06are here and here, so we can safely guess
    • 0:30:09that this is the same [? person. ?]
    • 0:30:10DAVID MALAN: Yeah, exactly.
    • 0:30:11And to summarize for the camera here, we have trained the software, if you will,
    • 0:30:15by giving it a photo of Toby's face.
    • 0:30:17So, by looking for the same or, really, similar pixels--
    • 0:30:20especially if it's a slightly different image of Toby--
    • 0:30:22we can, perhaps, identify him in the crowd.
    • 0:30:24And what really is a human face?
    • 0:30:26Well, at the end of the day, the computer
    • 0:30:28only knows it as a pattern of bits or, really,
    • 0:30:30at a higher level, a pattern of pixels.
    • 0:30:32So maybe a human face is, perhaps, best defined, in general,
    • 0:30:35as two eyes and a nose and a mouth that, even though all of us look similar,
    • 0:30:39structurally, odds are, the measurement between the eyes and the nose
    • 0:30:43and the width of the mouth, the skin tone and all
    • 0:30:45of these other physical characteristics are patterns
    • 0:30:47that software could, perhaps, detect and then look, statistically,
    • 0:30:51through the image, looking for the closest possible match
    • 0:30:53to these various measurement shapes, colors and sizes and the like.
    • 0:30:57And, indeed, that might be the intuition.
    • 0:30:59But what's powerful here, again, is just how easy and readily available
    • 0:31:03this technology now is.
    • 0:31:06All right.
    • 0:31:06So with that said, let's propose to consider what more we
    • 0:31:10can do with Python itself, get back to the fundamentals, so that you,
    • 0:31:13yourselves can start to implement something along those same lines.
    • 0:31:16So besides having access to things like a get_string function,
    • 0:31:21the CS50 library provides a few other things, as well-- namely, in C,
    • 0:31:26we had these.
    • 0:31:27But in Python, we're going to have fewer.
    • 0:31:29In Python, our library, short-term, is going to give you not only get_string,
    • 0:31:32but also get_int and get_float.
    • 0:31:33Why?
    • 0:31:34It's actually just annoying, as we'll soon
    • 0:31:36see, to get back an integer or a float from a user
    • 0:31:39and just make sure that it's an int and a float and not a word like cat or dog,
    • 0:31:44or some string that's not actually a number.
    • 0:31:47Well, we can import not just the specific function, get_string,
    • 0:31:50but we can actually import all of these functions one at a time,
    • 0:31:53like this, as we'll soon see.
    • 0:31:55Or you can even, in Python, import specific functions from a file.
    • 0:31:59One of you asked a while back, when you include something like CS50.h
    • 0:32:04or standard I/O .h, you're actually getting all of the code in that file,
    • 0:32:08which, potentially, can add bulk to your own program or time.
    • 0:32:12In this case, when you import specific functions from Python,
    • 0:32:15you can be a little more narrowly precise
    • 0:32:17as to what it is you want to have access to.
    • 0:32:21All right.
    • 0:32:21So, with that said, let's go ahead and see
    • 0:32:23what conditionals look like in Python.
    • 0:32:25So in the left-hand side again, here, we'll see Scratch.
    • 0:32:29So it's just a contrived example asking if x is less than y, then,
    • 0:32:33say, x is less than y.
    • 0:32:35In C, it looked like this.
    • 0:32:37In Python, now, it's going to look like this instead.
    • 0:32:41And here's before in C, and here's after.
    • 0:32:44And just to call out a few of the obvious differences, what
    • 0:32:47has changed, in Python, for conditionals, it would seem?
    • 0:32:53What's the difference?
    • 0:32:53Yeah.
    • 0:32:54AUDIENCE: There's a lack of curly braces.
    • 0:32:55DAVID MALAN: Yeah.
    • 0:32:56So there's no more curly braces.
    • 0:32:57And, indeed, you don't use those.
    • 0:32:59What appears to be taking their place, if you might infer?
    • 0:33:04What seems to have taken their place?
    • 0:33:05What do you think?
    • 0:33:05AUDIENCE: [INAUDIBLE]
    • 0:33:06DAVID MALAN: So the colon at the start of this line, here.
    • 0:33:09But also even more important, now, is this indentation below it.
    • 0:33:13So some of you, and we know this from office hours,
    • 0:33:16have a habit of indenting everything on the left, right?
    • 0:33:19And it's just this crazy mess to look at.
    • 0:33:21Frustrating for you, surely.
    • 0:33:23But C and Clang is pretty tolerant when it
    • 0:33:25comes to things like white space in a program.
    • 0:33:27Python, uh-uh.
    • 0:33:29They realized, years ago, that-- let's help humans help themselves and just
    • 0:33:32require standard indentation.
    • 0:33:34So four spaces would be the norm here.
    • 0:33:36But because it's indented below that colon, that,
    • 0:33:38indeed, indicates that this, now, is part of that condition.
    • 0:33:42Something else has gone missing, versus C, in this conditional.
    • 0:33:46What else is a little simplified?
    • 0:33:47AUDIENCE: [INAUDIBLE]
    • 0:33:49DAVID MALAN: Yeah.
    • 0:33:50So no more parentheses.
    • 0:33:51You can still use them, especially when you need to,
    • 0:33:53logically, to do order of operations, like in math.
    • 0:33:56But in this case, if you just want to ask
    • 0:33:57a simple question, like if x less than y, you can just do it like that.
    • 0:34:01How about when you have an if else?
    • 0:34:02Well, this is almost the same, here, with these same changes.
    • 0:34:05In C, this looked like this.
    • 0:34:06And it's starting to get a bit bulky-- at least,
    • 0:34:08if we use our curly braces in this way.
    • 0:34:10In Python, we can tighten things up further, even though,
    • 0:34:13strictly speaking, in C, you don't always need the curly braces.
    • 0:34:15But here, gone are the parentheses, again.
    • 0:34:18Gone are the curly braces.
    • 0:34:20Indentation is consistent, and we've just added another keyword,
    • 0:34:23else, with the colon.
    • 0:34:24But no more semicolons, as well.
    • 0:34:26How about something larger, like this, in if, else, if else?
    • 0:34:30This one's a little curious.
    • 0:34:31But in C, it looked like this-- if, else, if else.
    • 0:34:35In Python, it now looks like this.
    • 0:34:38And there's, perhaps, one curiosity here that,
    • 0:34:40honestly, all these years later, I still can't
    • 0:34:41remember how to spell it half the time.
    • 0:34:43What's weird about this?
    • 0:34:46What do you spot as different?
    • 0:34:50Yeah, over here.
    • 0:34:51AUDIENCE: [INAUDIBLE]
    • 0:34:53DAVID MALAN: Yeah.
    • 0:34:54Instead of else if, it's elif.
    • 0:34:56Why?
    • 0:34:56[SIGHS] Apparently, else space if was just too many
    • 0:34:59keystrokes for humans to type, so they condensed it into this way.
    • 0:35:02Probably means it's a little more distinguishable, too,
    • 0:35:05for the computer between the if and the else, too.
    • 0:35:07But just something to remember, now.
    • 0:35:08It's, indeed, elif and not else if.
    • 0:35:10All right.
    • 0:35:11So what about variables in Python?
    • 0:35:12I've used a couple of them already, but let's
    • 0:35:16distill exactly how you define and declare these things, as well.
    • 0:35:19So, in Scratch, if we wanted to create a variable called counter
    • 0:35:22and set it equal, initially, to 0, we would do something
    • 0:35:25like this-- specify that it's an int, use the assignment operator,
    • 0:35:28end the thought with a semicolon.
    • 0:35:30In Python, it's just simpler.
    • 0:35:32You name the variable, use the assignment operator,
    • 0:35:34as before, you set it equal to some value, and that's it.
    • 0:35:37You don't mention the type.
    • 0:35:38You don't mention the semicolon or anything more.
    • 0:35:41What if you want to change a variable, like counter,
    • 0:35:44by 1-- that is, incremented by 1?
    • 0:35:46You have a few different ways here.
    • 0:35:47In C, we saw syntax like this, where you can say counter equals counter plus 1,
    • 0:35:51which, again, feels illogical.
    • 0:35:54How can counter equal counter plus 1?
    • 0:35:56But, again, we read this code, really, right to left, updating its value by 1.
    • 0:36:01In Python, it's almost the same.
    • 0:36:03You just get rid of the semicolon.
    • 0:36:04So that logic is there.
    • 0:36:05But recall, in C, we could do something slightly different
    • 0:36:08that we can also do in Python.
    • 0:36:09In Python, you can also, more succinctly,
    • 0:36:12do this-- plus equals, and then, whatever number you want to add.
    • 0:36:15Or you can even change it to subtract, if you prefer.
    • 0:36:17Sadly, gone is something you've probably typed a whole lot.
    • 0:36:21What was the other way you can add 1?
    • 0:36:23AUDIENCE: Plus plus?
    • 0:36:24DAVID MALAN: Plus plus is no more, sadly, in Python.
    • 0:36:26Just too many ways to do the same thing, so they got rid of it
    • 0:36:29in favor of just this syntax, here.
    • 0:36:31So keep that in mind, as well.
    • 0:36:33What about loops, when you want to do something in Python again and again.
    • 0:36:36Well, in Scratch, in week zero, here's how we meowed three times,
    • 0:36:39specifically.
    • 0:36:40In C, we had a couple of ways of doing this.
    • 0:36:42This was the more mechanical approach, where you create a variable called i.
    • 0:36:46You set it equal to 0.
    • 0:36:47You then do while i is less than 3, the following.
    • 0:36:51And then, you, yourself increment i again and again.
    • 0:36:54Mechanical in the sense that you have to implement all of these gears
    • 0:36:57and make them turn yourself, but this was a correct way to do that.
    • 0:37:01In Python, we can still achieve the same idea,
    • 0:37:03but we don't need the int keyword.
    • 0:37:05We don't need any of the semicolons.
    • 0:37:07We don't need the parentheses.
    • 0:37:08We don't need the curly braces.
    • 0:37:10We can't use the plus plus, so maybe that's
    • 0:37:12a minor step backwards if you're a fan.
    • 0:37:14But otherwise, the code, the logic is exactly the same.
    • 0:37:17But there's other ways to achieve this same idea.
    • 0:37:20Recall that, in C, we could also do this.
    • 0:37:22You could use a for loop, which does exactly the same thing.
    • 0:37:25Both are correct.
    • 0:37:26Both are, arguably, well-designed.
    • 0:37:28It's to each their own when it comes to choosing between these.
    • 0:37:32In Python, though, we're going to have to think through how to do this.
    • 0:37:35So you don't do the same for loop as in C. The closest I could come up with
    • 0:37:41is this, where you say for i--
    • 0:37:44or whatever variable you want to do the counting-- in-- literally
    • 0:37:47the preposition-- and then, you use square brackets here.
    • 0:37:50And we've used square brackets before, in the context
    • 0:37:52of arrays and things like that.
    • 0:37:55And the 0, 1, 2 looks like an array, in some sense, even though we've also seen
    • 0:38:00arrays with curly braces.
    • 0:38:01But these square brackets, for now, denote a list.
    • 0:38:03Python does not have arrays.
    • 0:38:05An array is that contiguous chunk of memory, back to back to back,
    • 0:38:08that you have to resize somehow by moving things around in memory,
    • 0:38:13as per two weeks ago.
    • 0:38:14In Python, though, you can just create a list like this using square brackets.
    • 0:38:19And better still, as we'll see, you can add or even remove things
    • 0:38:22from that list down the road.
    • 0:38:24This, though, is not going to be very well-designed.
    • 0:38:27This will work.
    • 0:38:28This will iterate in Python three times.
    • 0:38:32But what might rub you the wrong way about this design,
    • 0:38:34even if you've never seen Python before?
    • 0:38:36How does this example not end well?
    • 0:38:38Yeah?
    • 0:38:38AUDIENCE: Making a large list [INAUDIBLE]..
    • 0:38:41DAVID MALAN: Yeah.
    • 0:38:42If you're making a large list, you have to type out each one of these numbers,
    • 0:38:45like comma 3, comma 4, comma 5, comma, dot, dot, dot, 50 comma, dot, dot, dot,
    • 0:38:50500.
    • 0:38:50Like, surely, that's not the best solution,
    • 0:38:52to have all of these numbers on the screen,
    • 0:38:55wrapping endlessly on the screen.
    • 0:38:57So, in Python, another way to do this would be to use a function
    • 0:39:01called range, which, technically, is a data type onto itself.
    • 0:39:04And this returns to you as many values as you ask for it.
    • 0:39:08range takes some other arguments, as well.
    • 0:39:09But the simplest use case here is, if you want back the numbers 0, 1, and 2--
    • 0:39:14a total of three values--
    • 0:39:15you say, hey, Python, please give me a range of three values.
    • 0:39:19And by default, they start at 0 on up.
    • 0:39:21But this is more efficient than it would be
    • 0:39:24to hard code the entire list at once.
    • 0:39:26And the best metaphor I could come up with is something like this.
    • 0:39:29Here, for instance, is a deck of cards.
    • 0:39:30This is normal, human size, and there's presumably 52 cards here.
    • 0:39:34So writing out 0 through 51 on code would be a little ridiculous
    • 0:39:38for the reasons you know.
    • 0:39:39And it would just be very unwieldy and ugly and wrapping in all of that.
    • 0:39:44It would be the virtual equivalent of me handing you all of these cards at once
    • 0:39:48to just deal with.
    • 0:39:49And, right, they're not that big, but it's a lot of cards to hold on to.
    • 0:39:52It requires a lot of memory or physical storage, if you will.
    • 0:39:55What range does, metaphorically, is, if you ask me for three cards,
    • 0:39:59I hand you them one at a time, like this, so that, at any point in time,
    • 0:40:04you only have one number in the computer's memory
    • 0:40:08until you're handed the next.
    • 0:40:09The alternative-- the previous version would
    • 0:40:11be to hand me all three cards at once, or all 52 cards at once.
    • 0:40:15But in this case, range is just way more efficient.
    • 0:40:17You can do range of 1,000.
    • 0:40:19That's not going to give you a list of 1,000 values all at once.
    • 0:40:22It's going to give you 1,000 values one at a time,
    • 0:40:25reducing memory significantly in the computer itself.
    • 0:40:30All right.
    • 0:40:31So, besides this, what about doing something forever in Scratch?
    • 0:40:34Well, we could do this, literally, with a forever block, which didn't quite
    • 0:40:38exist in C. In C, we had to hack it together by saying while True--
    • 0:40:42because True is, by definition, T-R-U-E, always true.
    • 0:40:46So this just deliberately induces an infinite loop for us.
    • 0:40:50In Python, the logic's going to be almost the same.
    • 0:40:53And infinite loops in Python tend to actually
    • 0:40:55be even more common because you can always break out of them, as you could
    • 0:40:58in C. In Python, it looks like this.
    • 0:41:02And this is slightly more subtle, but gone are the curly braces.
    • 0:41:05Gone are the parentheses.
    • 0:41:07But ever so slight difference, too?
    • 0:41:10A capital T for True and it's going to be a capital F for False.
    • 0:41:13Stupid little differences.
    • 0:41:14Eventually, you're going to mistype one or the other.
    • 0:41:16But these are the kinds of things to keep an eye out
    • 0:41:18and to start recognizing in your mind's eye when you read code.
    • 0:41:21Questions, now, on any of these building blocks?
    • 0:41:25Yeah?
    • 0:41:26AUDIENCE: In the for loop, was i set to 0 once for [? every loop? ?]
    • 0:41:31DAVID MALAN: In the for loop, was i--
    • 0:41:33it was set to 0 on the first iteration, then 1 on the next,
    • 0:41:37then 2 on the third.
    • 0:41:38And the same thing for range.
    • 0:41:39It just doesn't use up as much memory all at once.
    • 0:41:44Other questions, now, on any of these building blocks of Python?
    • 0:41:49All right.
    • 0:41:50Well, let's go ahead and build something a little more than hello.
    • 0:41:53Let me propose that, over here, we implement, maybe,
    • 0:41:56the simplest of calculators here.
    • 0:41:58So let me go back to VS Code here, open my terminal window
    • 0:42:02and open up, say, a file called calculator.py.
    • 0:42:06And in calculator.py, we'll have an opportunity
    • 0:42:09to explore some of these building blocks,
    • 0:42:11but we'll allow things to escalate pretty quickly
    • 0:42:13to more interesting examples so that we can do the same thing, ultimately,
    • 0:42:17as well.
    • 0:42:17And, in fact, let me go ahead and do this.
    • 0:42:19Moreover, I've brought some code with me in advance.
    • 0:42:22For instance, something called calculator0.c,
    • 0:42:25from the first week of C. And let me go ahead
    • 0:42:28and split my window here, in fact, so that I can now do something like this.
    • 0:42:34Let me move this over here, here.
    • 0:42:37Calculator.py.
    • 0:42:38So now, I have, on the left of my screen, calculator.c--
    • 0:42:40or calculator0.c because that's the first version I
    • 0:42:43made-- and calculator.py on the right.
    • 0:42:45Let me go ahead and implement, really, the same idea here.
    • 0:42:48So on the right-hand side, the analog of including cs50.h
    • 0:42:51would be from cs50 import get_int if I want to, indeed, use this function.
    • 0:42:56Now, I'm going to go ahead and give myself
    • 0:42:58a variable x without defining its type.
    • 0:43:00I'm going to use this get_int function and I'm
    • 0:43:02going to prompt the user for x, just like in C.
    • 0:43:05I'm, then, going to go ahead and prompt the user for another int,
    • 0:43:08like y, here, just like in C. And at the very end, I'm going to go ahead
    • 0:43:12and do print x plus y.
    • 0:43:14And that's it.
    • 0:43:15Now, granted, I have some comments in my C version of the code,
    • 0:43:19just to remind you of what each line is doing.
    • 0:43:21But I've still distilled this into six lines-- or, really, four
    • 0:43:23if I get rid of the blank line.
    • 0:43:25So it's already, perhaps, a bit tighter here.
    • 0:43:29It's tighter because something really important, historically, is missing.
    • 0:43:33What did I seem to omit altogether that we haven't really highlighted yet?
    • 0:43:38Yeah?
    • 0:43:39AUDIENCE: [INAUDIBLE]
    • 0:43:40DAVID MALAN: Yeah.
    • 0:43:41The main function is gone.
    • 0:43:42And in fact, maybe you took for granted that it just
    • 0:43:45worked a moment ago when I wrote hello, but I didn't
    • 0:43:47have a main function in hello, either.
    • 0:43:49And this, too, is a feature of Python and a lot of other languages, as well.
    • 0:43:52Instead of having to adhere to these long-standing traditions,
    • 0:43:55if you just want to write code and get something done, fine.
    • 0:43:57Just write code and get something done without, necessarily,
    • 0:43:59all of this same boilerplate.
    • 0:44:01So whatever is in your Python file--
    • 0:44:04left indented, if you will, by default--
    • 0:44:06is just going to be the code that the interpreter runs, top to bottom,
    • 0:44:10left to right.
    • 0:44:10Well, let me go ahead, now, and run code like this.
    • 0:44:14Let me go ahead and open back up my terminal window,
    • 0:44:17run python of calculator.py.
    • 0:44:19And I'll do x is 1, y is 2.
    • 0:44:21And as you might expect, it gives me 3.
    • 0:44:23Slight aesthetic bug.
    • 0:44:24I put my space in the wrong place here.
    • 0:44:26So that's a newbie mistake.
    • 0:44:27Let me fix that, aesthetically.
    • 0:44:29Let me rerun python of calculator.py.
    • 0:44:31Type in 1.
    • 0:44:31Type in 2.
    • 0:44:32And, voila, there is now my same version again.
    • 0:44:36But let me propose, now, that we get rid of this training wheel.
    • 0:44:39We don't want to keep taking one step forward
    • 0:44:41and then two steps back by adding these training wheels,
    • 0:44:43so let me instead do this.
    • 0:44:45In my version of calculator.py, suppose that we take away, already,
    • 0:44:49the training wheel that is the CS50 library here and let me,
    • 0:44:53instead, then, use just Python's built-in function called
    • 0:44:56input, which literally does just that.
    • 0:44:59It gets input from the user and it stores it, as before, in x and y.
    • 0:45:03So this is not CS50-specific.
    • 0:45:04This is real-world Python programming.
    • 0:45:07Well, let me go ahead and run, again, python of calculator.py.
    • 0:45:10And, of course, if x is 1 and y is 2, x plus y should, of course, still be 3.
    • 0:45:19It's apparently 12, according to Python, until CS50's library gets involved.
    • 0:45:24But does anyone want to infer what just went wrong?
    • 0:45:28Yeah?
    • 0:45:29AUDIENCE: We're always [INAUDIBLE].
    • 0:45:32DAVID MALAN: Exactly.
    • 0:45:33The input function, by design, always returns a string of text.
    • 0:45:37After all, that's what the human typed in.
    • 0:45:39And even though, yes, I typed the number keys on the keyboard,
    • 0:45:42it's still coming back as all text.
    • 0:45:44Now, maybe we should use like a get_int function.
    • 0:45:47Well, that doesn't exist in Python.
    • 0:45:48All you can do is get textual input-- a string from the user.
    • 0:45:52But we can convert one to the other.
    • 0:45:54And so, a fix for this so that we don't accidentally concatenate--
    • 0:45:58that is, join x plus y together-- would be to do something like this.
    • 0:46:02Let me go back to my Python code, here.
    • 0:46:04And whereas, in C, we could previously do typecasting--
    • 0:46:08we can convert one type to another--
    • 0:46:11that generally wasn't the case when you were doing something complex,
    • 0:46:14like a string to an int.
    • 0:46:15You could do a char to an int and vise versa.
    • 0:46:18But for a string, recall, there was a special function in the C-type library
    • 0:46:22called a to I, like Ascii to integer.
    • 0:46:25That's the closest analog, here.
    • 0:46:27And, in fact, the way to do this in Python
    • 0:46:29would be to use a function called int, which,
    • 0:46:32indeed, is the name of the data type, too,
    • 0:46:34even though I have not yet had to type it.
    • 0:46:36And I can convert the output of the input function
    • 0:46:40automatically from a string immediately to an int.
    • 0:46:44And now, if I go back to my terminal window, rerun python of calculator.py
    • 0:46:48with 1 and 2 for x and y, now, I'm back in business.
    • 0:46:52So that, then, is, for instance, what the CS50 library
    • 0:46:55does, if temporarily this week, is it just deals with the conversion for you.
    • 0:46:59And, in fact, bad things could happen if I type the wrong thing,
    • 0:47:03like dog or cat instead of a number.
    • 0:47:05But we'll cross that bridge in just a moment, as well.
    • 0:47:08All right.
    • 0:47:08What if we do something slightly different, now, with our calculator.
    • 0:47:16Instead of addition, let's do division instead.
    • 0:47:18So z equals x divided by y, thereby giving me a third variable z.
    • 0:47:23Let me go ahead and run python of calculator.py again.
    • 0:47:27I'll type in 1.
    • 0:47:29I'll type in 3 this time.
    • 0:47:31And what problem do you think we're about to see?
    • 0:47:37Or is it gone?
    • 0:47:38What happened when I did this in C, albeit with some slightly more
    • 0:47:41cryptic syntax, when I divided one number, like 1 divided by 3?
    • 0:47:47Anyone recall?
    • 0:47:48Yeah?
    • 0:47:49AUDIENCE: You would round to the nearest integer.
    • 0:47:51DAVID MALAN: Yeah.
    • 0:47:52So it would round down to the nearest integer,
    • 0:47:55whereby you experience truncation.
    • 0:47:57So if you take an integer like 1, you divide it
    • 0:48:00by another integer like 3, that technically
    • 0:48:02should be 0.33333, infinitely long.
    • 0:48:06But in C, recall, you truncate the value.
    • 0:48:10If you divide an int by an int, you get back
    • 0:48:12an int, which means you get only the integer part, which was the 0.
    • 0:48:14Now, Python actually handles this for us and avoids the truncation.
    • 0:48:18But it leaves us, still, with one other problem here, which is going to be,
    • 0:48:23for instance, not necessarily visible at a glance.
    • 0:48:27This looks correct.
    • 0:48:28This has solved the problem in C. So truncation does not happen.
    • 0:48:31The integers are automatically converted to a float-- a floating point value.
    • 0:48:36But what other problem did we trip over, back in week one?
    • 0:48:44What else got a little dicey when dealing with simple arithmetic?
    • 0:48:49Anyone recall?
    • 0:48:51Well, the syntax in Python is a little different,
    • 0:48:53but let me go ahead and do this.
    • 0:48:54It turns out, in Python, if you want to see more significant digits than what
    • 0:48:58I'm seeing here by default, which is a dozen or so, let me go ahead
    • 0:49:02and print out z as follows.
    • 0:49:03Let me first print out a format string because I want to format z
    • 0:49:07in an interesting way.
    • 0:49:08And notice, this would have no effect on the difference.
    • 0:49:11This is just a format string that, for no compelling reason at the moment,
    • 0:49:14is interpolating z in those curly braces using an fstring or format string.
    • 0:49:19If I run this again with 1 and 3, we'll see, indeed, the exact same thing.
    • 0:49:23But when you use an fstring, you, indeed,
    • 0:49:25have the ability to format that string more precisely.
    • 0:49:28Just like with %f in Python, you could start to fine-tune how many significant
    • 0:49:32digits you see--
    • 0:49:35in C, rather.
    • 0:49:37In Python, you can do the same, but the syntax is a little different.
    • 0:49:40If you want the computer to interpolate z and show you
    • 0:49:4350 significant digits-- that is, 50 numbers
    • 0:49:47after the decimal point-- syntax is similar to C,
    • 0:49:50but it's a little different.
    • 0:49:51You literally put a colon after the variable's name.
    • 0:49:54dot 50 means show me the decimal point and, then, 50 digits to the right,
    • 0:49:59and the f just indicates please treat this as a floating point value.
    • 0:50:02So now, if I rerun python of calculator.py,
    • 0:50:05divide 1 by 3, unfortunately, Python has not solved all of the world's problems
    • 0:50:11for us.
    • 0:50:12This, again, was an example of floating point imprecision.
    • 0:50:15So that problem is still latent.
    • 0:50:17So just because the world has advanced, doesn't necessarily
    • 0:50:20mean that all of our problems from C have gone away.
    • 0:50:22There are solutions using third-party libraries for scientific calculations
    • 0:50:26and the like.
    • 0:50:26But out of the box, floating point imprecision is still an issue.
    • 0:50:31Meanwhile, there was one other problem in C
    • 0:50:35that we ran into involving numbers, and that was this-- integer overflow.
    • 0:50:39Recall that an integer in C only took up,
    • 0:50:41what, 32 bits typically, which meant you could count as high as 4 billion
    • 0:50:45or, maybe, if you're doing positive and negatives, as high as 2 billion,
    • 0:50:48after which, weird things would happen.
    • 0:50:50The number would go to 0 or negative or it would overflow or wrap back around.
    • 0:50:54Well, wonderfully, in Python, they did, at least,
    • 0:50:56address this, whereby you can count as high as you want.
    • 0:51:00And Python will just use more and more and more and more
    • 0:51:03bits and bytes to store really big numbers so integer overflow is not
    • 0:51:08a thing.
    • 0:51:09With that said, Python is limited to how many digits it will show you
    • 0:51:13on the screen at once as a string.
    • 0:51:15But, mathematically, your math will be correct now.
    • 0:51:18So we've taken a couple of steps forward, one step sideways.
    • 0:51:21But, indeed, we have solved some of our problems here.
    • 0:51:25All right.
    • 0:51:26Questions, now, on any of these examples thus far?
    • 0:51:32Question?
    • 0:51:34All right.
    • 0:51:35Well, how about another problem that we encountered in C. Let's
    • 0:51:40revisit it here in Python, as well.
    • 0:51:41So let me go ahead and, on the left-hand side
    • 0:51:43here, let me open up a file called, say, compare3.c on the left,
    • 0:51:54and let me go ahead and create a new file on the right called compare.py.
    • 0:51:57Because recall that bad things happened when
    • 0:52:00we needed to compare two values in C. So on the left,
    • 0:52:03here, is a reminder of what we once did in C,
    • 0:52:06whereby, if we want to compare values, we can get an int in C, store it in x.
    • 0:52:11A get_int in C, store it in y.
    • 0:52:13We then have our familiar, conditional logic here,
    • 0:52:16just printing out if x x less than y or not.
    • 0:52:19Well, we can certainly do the same thing, ultimately, in Python
    • 0:52:23by using some fairly familiar syntax.
    • 0:52:25And let's just demonstrate this one quickly.
    • 0:52:27Let me go over here, too.
    • 0:52:29I'll do from cs50 import get_int, even though I could do this, instead,
    • 0:52:34with the input function itself.
    • 0:52:36x equals get_int, and I'll prompt the user for that.
    • 0:52:39y equals get_int, and I'll prompt the user for that.
    • 0:52:42After that, recall that I can say, without parentheses,
    • 0:52:45if x is less than y, then print out, without the f, "x is less than y."
    • 0:52:52Then, I can go ahead and say else if x is greater than y, I can print out,
    • 0:52:58quote unquote, "x is greater than y."
    • 0:53:01If you'd like to interject now, what did I screw up?
    • 0:53:05Anyone?
    • 0:53:05Yeah?
    • 0:53:06AUDIENCE: Elif.
    • 0:53:06DAVID MALAN: Elif, right?
    • 0:53:07So elif x is greater than y, else-- this part's the same-- print
    • 0:53:13"x is equal to y."
    • 0:53:18There's no new logic going on here.
    • 0:53:19But, at least syntactically, it's a little cleaner.
    • 0:53:21Indeed, this program is only 11 lines long, albeit without any comments.
    • 0:53:25Let me go ahead and run python of compare.py.
    • 0:53:27Let's see.
    • 0:53:28Is 1 less than 2?
    • 0:53:30Indeed.
    • 0:53:30Let's run it again.
    • 0:53:32Is 2 less than 1?
    • 0:53:33No, it's greater than.
    • 0:53:34And let's, lastly, type in 1 and 1 twice.
    • 0:53:37x is equal to y.
    • 0:53:38So we've got a pretty side-by-side, one-to-one conversion here.
    • 0:53:42Let's do something a little more interesting, then.
    • 0:53:44In C, how about I open, instead, something where we actually
    • 0:53:48compared for a purpose?
    • 0:53:49So if I open up, from earlier in the course--
    • 0:53:54how about agree.c, which prompt the user to agree to something or not?
    • 0:54:00And let me code up a new version here, called agree.py.
    • 0:54:03And I'll do this on the right-hand side, with agree.py.
    • 0:54:06But on agree.c on the left--
    • 0:54:08notice that this is how we did this yes-no thing in C--
    • 0:54:12we compared c, a character, equal to single quotes 'Y'
    • 0:54:16or equal to single quotes little 'y.'
    • 0:54:18And then, the same thing for n.
    • 0:54:20Now, in Python, this one is actually going
    • 0:54:22to be a little bit different, here.
    • 0:54:23Let me go ahead and, in the Python version of this,
    • 0:54:27let me do something like this.
    • 0:54:29We'll use get_string.
    • 0:54:31Actually, no.
    • 0:54:31We'll just use input in this case.
    • 0:54:33So let's do s equals input.
    • 0:54:36And we'll ask the user the same thing--
    • 0:54:38Do you agree, question mark.
    • 0:54:40Then, let's go ahead and say, if s equals equals--
    • 0:54:46how about Y?
    • 0:54:48Huh.
    • 0:54:49How do I do this?
    • 0:54:50Well, a few things.
    • 0:54:51Turns out, I'm going to do this-- s equals equals little y.
    • 0:54:54Then, I'm going to go ahead and print out "Agreed."
    • 0:54:57And elif s equals equals capital N or s equals equals lowercase n,
    • 0:55:03I'm going to go ahead and print out "Not agreed."
    • 0:55:05And I claim, for the moment, that this is identical, now,
    • 0:55:08to the program on the left in C. But what's different?
    • 0:55:13So we're still doing the same kind of logic, these equal equals
    • 0:55:17for comparing for equality.
    • 0:55:18But notice that, nicely enough, Python got rid of the two vertical bars,
    • 0:55:21and it's just literally the word "or."
    • 0:55:23If you recall seeing ampersand ampersand to express a logical and in C, [GRUNTS]
    • 0:55:27you can just write, literally, the word "and."
    • 0:55:29And so, here's a hint of why Python tends to be pretty popular.
    • 0:55:33People just like that it's a little closer to English.
    • 0:55:35There's a little less of the cryptic syntax here.
    • 0:55:38Now, this is correct, as this code will now work.
    • 0:55:41But I've also used double quotes instead of single quotes,
    • 0:55:45and I also omitted, a few minutes ago, from my list of data
    • 0:55:48types in Python the word "char."
    • 0:55:51In Python, there are no chars.
    • 0:55:53There are no individual characters.
    • 0:55:55If you want to manipulate an individual character, you use a string--
    • 0:55:58that is to say, a str--
    • 0:56:00of size 1.
    • 0:56:01Now, in Python, you can use single quotes or double quotes.
    • 0:56:04I'm deliberately using double quotes everywhere,
    • 0:56:06just for consistency with how we treat strings in C.
    • 0:56:09It's pretty common, though, to use single quotes instead,
    • 0:56:12if only because, on most keyboards, you don't
    • 0:56:14have to hold the Shift key anymore.
    • 0:56:16Humans have really started to optimize just how
    • 0:56:18quickly they want to be able to code.
    • 0:56:19So using a single quote tends to be pretty popular
    • 0:56:22in Python and other languages, as well.
    • 0:56:24They are fundamentally the same, single or double, unlike in C,
    • 0:56:29where they have meaning.
    • 0:56:30So this is correct, I claim.
    • 0:56:33And, in fact, let me run this real quick.
    • 0:56:34I'll open up my terminal window here.
    • 0:56:37Let me get rid of the version in C and run python of agree.py.
    • 0:56:40And I'll type in Y. OK.
    • 0:56:42I'll run it again and type in little y.
    • 0:56:44And I'll stipulate it's going to work for no, as well.
    • 0:56:46But this isn't necessarily the only way we can do this.
    • 0:56:49There are other ways to implement the same idea.
    • 0:56:52And in fact, I can go about doing this instead.
    • 0:56:57Let me go back up to my code here.
    • 0:56:59And we saw a hint of this earlier.
    • 0:57:03We know that lists exist in Python, and you can create them
    • 0:57:06just by using square brackets.
    • 0:57:08So what if I simplify the code a little bit and just
    • 0:57:10say if s is in the following list of values--
    • 0:57:14capital Y or lowercase y.
    • 0:57:17It's not all that different, logically, but it's a little tighter.
    • 0:57:21It's a little more compact.
    • 0:57:22So elif s is in capital N or lowercase n, I can express that same idea, too.
    • 0:57:29So here, again, it's just getting a little more pleasant to write code.
    • 0:57:32There's less hitting of the keyboard.
    • 0:57:33You can express yourself a little more succinctly.
    • 0:57:36And using the keyword in, Python will figure out
    • 0:57:40how to search the entire list for whatever the value of s is.
    • 0:57:44And if it finds it, it will return True automatically.
    • 0:57:47Else, it will return False.
    • 0:57:48So if I run agree.py again and type in capital Y or lowercase y, that still,
    • 0:57:54now, works.
    • 0:57:55Well, I can tighten this up further if I want to add more features.
    • 0:58:00Well, what if I want to support not just big Y and little y,
    • 0:58:04but how about "Yes" or "yes" or, in case the user
    • 0:58:10is yelling or someone who isn't good with CapsLock types in "YES?"
    • 0:58:14Wait a minute.
    • 0:58:14But it could be weird.
    • 0:58:16Do we want to support this or this?
    • 0:58:20This just gets really tedious, quickly, combinatorially,
    • 0:58:23if you consider all of these possible permutations.
    • 0:58:25What would be smarter than doing something
    • 0:58:27like this, if you want to just be able to tolerate
    • 0:58:30"yes" in any form of capitalization?
    • 0:58:33Logically, what would be nice?
    • 0:58:35AUDIENCE: Maybe, whatever the input is, you just transfer it over
    • 0:58:38to all lowercase while uppercase, and then redo it?
    • 0:58:40DAVID MALAN: Exactly.
    • 0:58:41Super common paradigm.
    • 0:58:42Why don't we just force the user's input to all lowercase or all uppercase--
    • 0:58:46doesn't matter, so long as we're self-consistent-- and just compare
    • 0:58:49against all uppercase or all lowercase.
    • 0:58:52And that will get rid of all of the possible permutations, otherwise.
    • 0:58:55Now, in C, we might have done something like this.
    • 0:58:58We might have simplified this whole list and just said--
    • 0:59:01let's say we'll do--
    • 0:59:04how about lowercase?
    • 0:59:06So y or yes, and we'll just leave it at that.
    • 0:59:10But we need to force, now, s to lowercase.
    • 0:59:12Well, in C, we would have used the C-type library.
    • 0:59:15We would have done to.lower and call that function, passing it in.
    • 0:59:19Although, not really because, in C-type, those
    • 0:59:22operate on individual characters or chars, not whole strings.
    • 0:59:25We actually didn't see a function that could convert a whole string in C
    • 0:59:29to lowercase.
    • 0:59:31But in Python, we're going to benefit from some other feature, as well.
    • 0:59:34It turns out that Python supports what's called object-oriented programming.
    • 0:59:39And we're only going to scratch the surface of this in CS50.
    • 0:59:41But if you take a higher-level C course in programming or CS,
    • 0:59:44you explore this as a different paradigm.
    • 0:59:46Up until now, in C, we've been focusing on what's called, really,
    • 0:59:49procedural programming.
    • 0:59:51You write procedures.
    • 0:59:52You write functions, top to bottom, left to right.
    • 0:59:55And when you want to change some value, we
    • 0:59:57were in the habit of using a procedure-- that is, a function.
    • 1:00:00You would pass something, like a variable, into a function,
    • 1:00:03like toupper or tolower, and it would do its thing and hand you back a value.
    • 1:00:07Well, it turns out that it would be nicer, programming-wise, if some data
    • 1:00:12types just had built-in functionality.
    • 1:00:15Why do we have our variables over here and all of our helper functions,
    • 1:00:18like toupper and tolower over here, such that we constantly
    • 1:00:21have to pass one into the other.
    • 1:00:22It would be nice to bake into our data type some built-in functionality
    • 1:00:27so that you can change variables using their own, default built-in
    • 1:00:33functionality.
    • 1:00:33And so, Object-Oriented Programming, otherwise known as OOP,
    • 1:00:37is a technique whereby certain types of values, like a string--
    • 1:00:41AKA str-- not only have properties inside of them--
    • 1:00:47attributes, just like a struct in C--
    • 1:00:49your data can also have functions built into them, as well.
    • 1:00:54So, whereas in C, which is not object-oriented, you have structs.
    • 1:00:57And structs can only store data, like a name and a number
    • 1:01:01when implementing a person.
    • 1:01:02In Python, you can, for instance, have not just a structure--
    • 1:01:07otherwise known as a class--
    • 1:01:09storing a name and a number.
    • 1:01:10You can have a function call that person or email that person
    • 1:01:15or actual verbs or actions associated with that piece of data.
    • 1:01:19Now, in the context of strings, it turns out
    • 1:01:21that strings come with a lot of useful functionality.
    • 1:01:24And in fact, at this URL here, which is in docs.python.org,
    • 1:01:28which is the official documentation for Python,
    • 1:01:31you'll see a whole list of methods--
    • 1:01:34that is, functions-- that come with strings that you can actually
    • 1:01:37use to modify their values.
    • 1:01:40And what I mean by this is the following.
    • 1:01:42If we go through the documentation, poke around,
    • 1:01:44it turns out that strings come with a function called lower.
    • 1:01:48And if you want to use that function, you just
    • 1:01:50have to use slightly different syntax than in C. You do not do tolower,
    • 1:01:54and you do not say, as I just did, lower because this function is
    • 1:01:59built into s itself.
    • 1:02:01And just like in C, when you want to go inside of a variable, like a structure,
    • 1:02:05and access a piece of data inside of it, like name or number,
    • 1:02:09when you also have functions built into data types--
    • 1:02:12AKA methods; a method is just a function that is built into a piece of data--
    • 1:02:17you can do s dot lower open paren, closed paren in this case.
    • 1:02:23And I can do this down here, as well.
    • 1:02:25If s.lower in, quote unquote, "n" or "no", the whole thing,
    • 1:02:33I can force this whole thing to lowercase.
    • 1:02:35So the only difference here, now, as an object-oriented programming,
    • 1:02:38instead of constantly passing a value into a function,
    • 1:02:41you just access a function that's inside of the value.
    • 1:02:45It just works because of how the language itself is defined.
    • 1:02:48And the only way you know whether these functions exist
    • 1:02:51is the documentation-- a class, a book, a website or the like.
    • 1:02:55Questions, now, on this technique?
    • 1:03:00All right.
    • 1:03:01I claim this is correct.
    • 1:03:02Now, even though you've never programmed, most of you, in Python
    • 1:03:05before, not super well-designed.
    • 1:03:07There's an subtle inefficiency, now, on lines 3 and 5 together.
    • 1:03:12What's dumb about how I've used lower, might you think?
    • 1:03:18Yeah?
    • 1:03:18AUDIENCE: I feel like, using it twice, you'd just want another [? variable. ?]
    • 1:03:21DAVID MALAN: Yeah.
    • 1:03:22If you're going to use the same function twice and ask the same question,
    • 1:03:25expecting the same answer, why are you calling the function itself twice?
    • 1:03:29Maybe we should just store the result in a variable.
    • 1:03:31So we could do this in a couple of different ways.
    • 1:03:33We, for instance, could go up here and create another variable called t
    • 1:03:36and set that equal to s.lower.
    • 1:03:38And then, we could just change this to be t, here.
    • 1:03:41But honestly, I don't think we technically
    • 1:03:43need another variable altogether, here.
    • 1:03:45I could just do something like this.
    • 1:03:47Let's change the value of s to be the lowercase version thereof.
    • 1:03:52And so, now, I can quite simply refer to s again and again like this,
    • 1:03:55reusing that same value.
    • 1:03:57Now, to be sure, I have now just lost the user's original input.
    • 1:04:01And if I care about that-- if they typed in all caps, I have no idea anymore.
    • 1:04:05So maybe I do want to use a separate variable, altogether.
    • 1:04:08But a takeaway here, too, is that strings in Python
    • 1:04:10are technically what we'll call immutable--
    • 1:04:13that is, they cannot be changed.
    • 1:04:15This was not true in C. Once we gave you arrays in week two
    • 1:04:19or memory in week four, you could go to town on a string
    • 1:04:22and change any of the characters you want-- uppercasing, lowercasing,
    • 1:04:25changing it, shortening it and so forth.
    • 1:04:27But in this case, this returns a copy of s, forced to lowercase.
    • 1:04:33It doesn't change the original string--
    • 1:04:35that is, the bytes in the computer's memory.
    • 1:04:38When you assign it back to s, you're essentially
    • 1:04:41forgetting about the old version of s.
    • 1:04:43But because Python does memory management for you-- there's no malloc,
    • 1:04:46there's no free--
    • 1:04:47Python automatically frees up the original bytes, like Y-E-S,
    • 1:04:52and hands them back to the operating system for you.
    • 1:04:54All right.
    • 1:04:55Questions, now, on this technique?
    • 1:04:59Questions on this?
    • 1:05:02In general, I'll call out-- the Python documentation
    • 1:05:05will start to be your friend because, in class, we'll only scratch
    • 1:05:07the surface with some of these things.
    • 1:05:09But in docs.python.org, for instance, there's
    • 1:05:12a whole reference of all of the built-in functions that come with the language,
    • 1:05:15as well as, for instance, those with a string.
    • 1:05:18All right.
    • 1:05:19Before we take a break, let's go ahead and create something a little familiar
    • 1:05:23too based on our weeks here, in C. Let me
    • 1:05:27propose that we revisit those examples involving some meows.
    • 1:05:30So, for instance, when we had our cat meow back in the first week
    • 1:05:34and, then, second in C, we did something that was a little stupid at first
    • 1:05:37whereby we created a file, as I'll do here-- this time, called meow.py.
    • 1:05:41And if I want a cat to meow three times, I
    • 1:05:44could run it once, like this, a little copy-paste.
    • 1:05:47And now, python of meow.py, and I'm done.
    • 1:05:50Now, we've visited this example two times, at least,
    • 1:05:53now in Scratch and in C.
    • 1:05:54It's correct, I'll stipulate, but what's, obviously, poorly designed?
    • 1:06:00What's the fault here?
    • 1:06:01Yeah?
    • 1:06:02AUDIENCE: It should just be a loop.
    • 1:06:03DAVID MALAN: It should just be a loop, right?
    • 1:06:04Why type it three times?
    • 1:06:05Literally, copying and pasting is almost always a bad thing--
    • 1:06:08except in C, when you have the function prototypes that you need to borrow.
    • 1:06:11But in this case, this is just inefficient.
    • 1:06:13So what could we do better here, in Python?
    • 1:06:15Well, in Python, we could probably change this in a few different ways.
    • 1:06:18We could borrow some of the syntax we proposed in slide form
    • 1:06:21earlier, like give me a variable called i.
    • 1:06:23Set it to 0, no semicolon.
    • 1:06:26While i is less than 3-- if I want to do this three times--
    • 1:06:29I can go ahead and print out "meow."
    • 1:06:31And then, I can do i plus equals 1.
    • 1:06:33And I think this would do the trick.
    • 1:06:35Python of meow.py, and we're back in business already.
    • 1:06:38Well, if I wanted to change this to a for loop, well, in Python,
    • 1:06:41it would be a little tighter, but this would not be the best approach.
    • 1:06:44So for i in 0, 1, 2, I could just do print "meow", like this.
    • 1:06:52And that, too, would get the job done.
    • 1:06:54But, to our discussion earlier, this would get stupid pretty quickly
    • 1:06:58if you had to keep enumerating all of these values.
    • 1:07:00What did we introduce instead?
    • 1:07:03The range function.
    • 1:07:04Exactly.
    • 1:07:05So that hands me back, way more efficiently, just the values I want,
    • 1:07:09indeed, one at a time.
    • 1:07:10So even this, if I run it a third or fourth time, we've got the same result.
    • 1:07:14But now, let's transition to where we went with this back in the day.
    • 1:07:18How can we start to modularize this?
    • 1:07:20It would be nice, I claimed, if MIT had given us a meow function.
    • 1:07:24Wouldn't it be nice if Python had given us a meow function?
    • 1:07:27Maybe less compelling in Python, but how can I build my own function?
    • 1:07:30Well, I did this briefly with the spell checker earlier,
    • 1:07:33but let me go ahead and propose that we could implement, now,
    • 1:07:36our own version of this in Python as follows.
    • 1:07:40Let me go ahead and start fresh here and use the keyword def.
    • 1:07:44So this did not exist in C. You had the return value, the function
    • 1:07:47name, the arguments.
    • 1:07:48In Python, you literally say def to define a function.
    • 1:07:52You give it a name, like meow.
    • 1:07:54And now, I'm going to go ahead and, in this function, just print out meow.
    • 1:07:57And this lets me change it to anything else I want in the future.
    • 1:08:01But for now, it's an abstraction.
    • 1:08:03And in fact, I can move it out of sight, out of mind--
    • 1:08:07just going to hit Enter a bunch of times to pretend,
    • 1:08:09now, it exists, but I don't care how it is implemented.
    • 1:08:13And up here, now, I can do something like this.
    • 1:08:15For i in range of 3, let me go ahead and not print "meow" anymore.
    • 1:08:20Let me just call meow and tightening up my code further.
    • 1:08:25Let's see.
    • 1:08:25Python of meow.py.
    • 1:08:26This is, I think, going to be the first time it does not work correctly.
    • 1:08:31OK.
    • 1:08:32So here, we have, sadly, our first Python error.
    • 1:08:36And let's see.
    • 1:08:37The syntax is going to be different from C or Clangs output.
    • 1:08:40Traceback is the term of art here.
    • 1:08:41This is like a trace back of all of the lines of code
    • 1:08:44that were just executed or, really, functions you've called.
    • 1:08:47The file name is uninteresting.
    • 1:08:49This is my codespace, specifically, but the file name
    • 1:08:52is important here-- meow.py.
    • 1:08:53Our line 2 is the issue--
    • 1:08:55OK, I didn't get very far before I screwed up--
    • 1:08:58and then, there's a name error.
    • 1:08:59And you'll see, in Python, there's typically these capitalized keywords
    • 1:09:03that hint at what the issue is.
    • 1:09:05It's something related to names of variables. "meow" is not defined.
    • 1:09:09All right.
    • 1:09:09You're programming Python for the first time.
    • 1:09:11You've screwed up.
    • 1:09:12You're following some online tutorial.
    • 1:09:14You're seeing this.
    • 1:09:16Reason through it.
    • 1:09:18Why might "meow" not be defined?
    • 1:09:20What can we infer about Python?
    • 1:09:24How to troubleshoot, logically?
    • 1:09:27AUDIENCE: [INAUDIBLE]
    • 1:09:29DAVID MALAN: Maybe.
    • 1:09:29Is it because "meow" is defined after?
    • 1:09:32As smart as Python seems to be, vis-a-vis C,
    • 1:09:34they have some similar design characteristics.
    • 1:09:37So let's try that.
    • 1:09:37So let me scroll all the way back down to where I moved this earlier.
    • 1:09:41Let me get rid of it--
    • 1:09:43way down there.
    • 1:09:44I'll copy it to my clipboard.
    • 1:09:46And let me just hack something together.
    • 1:09:48Let me just put it up here.
    • 1:09:49And let's see if this works.
    • 1:09:51So now, let me clear my terminal, run python of meow.py.
    • 1:09:54OK.
    • 1:09:55We're back in business.
    • 1:09:56So that was actually really good intuition.
    • 1:09:57Good debugging technique, just reason through it.
    • 1:10:00Now, this is contradicting what I claimed back
    • 1:10:02in week one, which was that the main part of your program,
    • 1:10:05ideally, should just be at the top of the file.
    • 1:10:07Don't make me look for it.
    • 1:10:08It's not a huge deal with a four-line program,
    • 1:10:10but if you've got 40 lines or 400 lines, you
    • 1:10:13don't want the juicy part of your program
    • 1:10:15to be way down here, and all of these functions way up here.
    • 1:10:18So it would be nice, maybe, if we actually have a main function.
    • 1:10:22And so, it actually turns out to be a convention in Python
    • 1:10:25to define a main function.
    • 1:10:27It's not a special function that's automatically called, like in C.
    • 1:10:30But humans realized, you know what?
    • 1:10:32That was a pretty useful feature.
    • 1:10:34Let me define a function called main.
    • 1:10:36Let me indent these lines underneath it.
    • 1:10:39Let me practice what I'm preaching, which is put
    • 1:10:41the main code at the top of the file.
    • 1:10:43And, wonderfully, in Python, now, you do not need prototypes.
    • 1:10:47There's none of that hackish copying and pasting
    • 1:10:49of the return type, the name and the arguments to a function,
    • 1:10:52like we needed in C. This is now OK instead, except for one, minor detail.
    • 1:10:58Let me go ahead and run python of meow.py.
    • 1:11:01Hopefully, now, I've solved this problem by having [GROANS] a main function.
    • 1:11:05But now, nothing has happened.
    • 1:11:08All right.
    • 1:11:08Even if you've never programmed in Python before,
    • 1:11:12what might explain this behavior, and how do I fix?
    • 1:11:17Again, when you're off in the real world, learning some new language,
    • 1:11:20all you have is deductive logic to debug.
    • 1:11:23Yeah?
    • 1:11:24AUDIENCE: I remember in C, even though we [INAUDIBLE]..
    • 1:11:31DAVID MALAN: Right.
    • 1:11:32So the solution, to be clear, in C was that we
    • 1:11:34had to put the prototype up here.
    • 1:11:35Otherwise, we'd get an error message.
    • 1:11:36In this case, I'm actually not getting an error message.
    • 1:11:39And, indeed, I'll claim that you don't need the prototypes in Python.
    • 1:11:42Just not necessary because that was annoying, if nothing else.
    • 1:11:46But what else might explain?
    • 1:11:48Yeah, in the back?
    • 1:11:49AUDIENCE: [INAUDIBLE]
    • 1:11:51DAVID MALAN: Yeah.
    • 1:11:51Maybe you have to call main itself.
    • 1:11:53If main is not some special status in Python, maybe just because it exists
    • 1:11:58isn't enough.
    • 1:11:59And, indeed, if you want to call main, the new convention
    • 1:12:02is actually going to be-- as the very last line of your program,
    • 1:12:05typically-- to literally call main.
    • 1:12:07It's a little stupid-looking, but they made a design decision.
    • 1:12:10And this is how, now, we work around it.
    • 1:12:13Python of meow.py.
    • 1:12:14Now we're back in business.
    • 1:12:16But now, logically, why does this work the way it does?
    • 1:12:19Well, in this case-- top to bottom--
    • 1:12:22line 1 is telling Python to define a function called main
    • 1:12:25and, then, define it as follows, lines 2 and 3.
    • 1:12:27But it's not calling main yet.
    • 1:12:29Line 6 is telling Python how to define a function called meow,
    • 1:12:33but it's not calling these lines yet.
    • 1:12:35Now, on line 10, you're telling Python, call main.
    • 1:12:38And at that point, Python has been trained, if you will,
    • 1:12:41to know what main is on line 1, to know what meow is on line 6.
    • 1:12:45And so, it's now perfectly OK for main to be above meow
    • 1:12:49because you never called them yet.
    • 1:12:51You defined, defined, and then, you called.
    • 1:12:54And that's the logic behind this.
    • 1:12:56Any questions, now, on the structure of this technique, here?
    • 1:13:01Now, let's do one more, then.
    • 1:13:03Recall that the last thing we did in Scratch and in C was to,
    • 1:13:07actually, parameterize these same functions.
    • 1:13:10So suppose that you don't want main to be responsible for the loop here.
    • 1:13:14You instead want to, very simply, do something like "meow" three times
    • 1:13:17and be done with it.
    • 1:13:18Well, in Python, it's going to be similar in spirit to C.
    • 1:13:21But, again, we don't need to keep mentioning data types.
    • 1:13:23If you want "meow" to take some argument--
    • 1:13:26like a number n--
    • 1:13:27you can just specify n as the name of that argument.
    • 1:13:30Or you can call it anything else, of course, that you want.
    • 1:13:33You don't have to specify int or anything else.
    • 1:13:35In your code, now, inside of meow, you can do something like for i in,
    • 1:13:40let's say--
    • 1:13:41I definitely, now, can't do this because that would be weird, to start the list
    • 1:13:45and end it with n.
    • 1:13:46So, if I can come back over here, what's the solution?
    • 1:13:49How can I do something n times?
    • 1:13:51AUDIENCE: [INAUDIBLE]
    • 1:13:52DAVID MALAN: Yeah.
    • 1:13:53Using range.
    • 1:13:54So range is nice because I can pass in, now, this variable n.
    • 1:13:58And now, I can meow-- whoops.
    • 1:13:59Now i can print out, quote unquote, "meow."
    • 1:14:03So it's almost the same as in Scratch, almost the same as in C.
    • 1:14:05But it's a little simpler.
    • 1:14:06And if, now, I run meow.py, I'll have the ability, now, to do this here,
    • 1:14:12as well.
    • 1:14:13All right.
    • 1:14:13Questions on any of this?
    • 1:14:16Right now, we're taking this stroll through week one.
    • 1:14:19We're going to, momentarily, escalate things
    • 1:14:22to look not only at some of these basics,
    • 1:14:24but also, other features, like we saw with face recognition
    • 1:14:27with the speller or the like.
    • 1:14:28Because of how many of us are here, we have a huge amount of candy
    • 1:14:31out in the lobby.
    • 1:14:32So why don't we go ahead and take a 10-minute break?
    • 1:14:34And when we come back, we'll do even fancier, more powerful things
    • 1:14:37with Python in 10.
    • 1:14:38All right.
    • 1:14:40So we are back.
    • 1:14:41Among our goals, now, are to introduce a few more building
    • 1:14:44blocks so that we can solve more interesting problems at the end,
    • 1:14:47much like those that we began with.
    • 1:14:49You'll recall, from a few weeks ago, we played with this two-dimensional Super
    • 1:14:52Mario world.
    • 1:14:53And we tried to print a vertical column of three or more bricks.
    • 1:14:57Well, let me propose that we use this as an opportunity to, now,
    • 1:15:00tinker with some of Python's more useful, more
    • 1:15:02user-friendly functionality, as well.
    • 1:15:04So let me code a file called mario.py, and let's just print out
    • 1:15:09the equivalent of that vertical column.
    • 1:15:10So it's of height 3.
    • 1:15:12Each one is a hash, so let's do for i in range of 3 initially,
    • 1:15:16and let's just print out a single hash.
    • 1:15:18And I think, now, python of mario.py--
    • 1:15:21voila.
    • 1:15:22We're in business, printing out just that same column there.
    • 1:15:27What if, though, we want to print a column of some variable height
    • 1:15:31where the user tells us how tall they want it to be?
    • 1:15:33Well, let me go up here, for instance and, instead, how about--
    • 1:15:39let's do this.
    • 1:15:40How about from cs50 import?
    • 1:15:45How about the get_int function, as before?
    • 1:15:47So it will deal with making sure the user gives us an integer.
    • 1:15:50And now, in the past, whenever we wanted to get a number from a user,
    • 1:15:54we've actually followed a certain paradigm.
    • 1:15:56In fact, if I open up here, for instance,
    • 1:16:02how about mario1.c from a while back, you
    • 1:16:06might recall that we had code like this.
    • 1:16:11And we specifically use the do while loop in C
    • 1:16:13whenever we want to get something from the user,
    • 1:16:16maybe, again and again and again, until they cooperate.
    • 1:16:18At which point, we finally break out of the loop.
    • 1:16:20So it turns out, Python does have while loops,
    • 1:16:22does have for loops, does not have do while loops.
    • 1:16:25And yet, pretty much any time you've gotten user input,
    • 1:16:27you've probably used this paradigm.
    • 1:16:30So it turns out that the Python equivalent of this is to do,
    • 1:16:33similar in spirit, but using only a while loop.
    • 1:16:36And a common paradigm in Python, as I alluded earlier,
    • 1:16:39is to actually deliberately induce an infinite loop while True--
    • 1:16:43capital T-- and then, do what you want to do, like get an int from the user
    • 1:16:48and prompt them for the height, for instance, in question.
    • 1:16:51And then, if you're sure that the user has given you what you want--
    • 1:16:56like n is greater than 0, which is what I want, in this case,
    • 1:16:59because I want a positive integer; otherwise, there's nothing to print--
    • 1:17:02you literally just break out of the loop.
    • 1:17:04And so, we could actually use this technique in C. It's just not
    • 1:17:08really done in C. You could absolutely, in C,
    • 1:17:10have done a while True loop with the parentheses, lowercase true.
    • 1:17:13You could break out of it, and so forth.
    • 1:17:15But in Python, this is the Python way.
    • 1:17:18And this is actually a term of art.
    • 1:17:19This way in Python is pythonic This is "the way everyone does it,"
    • 1:17:24quote unquote.
    • 1:17:24Doesn't mean you have to, but that's the way the cool Python programmers would
    • 1:17:28implement an idea like this-- trying to do something again and again
    • 1:17:31and again until the user actually cooperates.
    • 1:17:34But all we've done is take away the do while loop.
    • 1:17:36But still, logically, we can implement the same idea.
    • 1:17:39Now, below this, let me go ahead and just print out, for i in range of n
    • 1:17:44this time-- because I want it to be variable and not 3.
    • 1:17:47I can go ahead and print out the hash--
    • 1:17:49let me go ahead and get rid of the C version here--
    • 1:17:52open my terminal window and I'll run, again, Python of mario.py.
    • 1:17:55I'll type in 3 and I get back those three hashes.
    • 1:17:58But if I, instead, type in 4, I now get four hashes instead.
    • 1:18:02So the takeaway here is, quite simply, that this
    • 1:18:04would be the way, for instance, to actually get back
    • 1:18:08a value in Python that is consistent with some parameter,
    • 1:18:11like greater than 0.
    • 1:18:13How about this?
    • 1:18:13Let's actually practice what we preached a moment ago with our meowing examples
    • 1:18:17and factoring all this out.
    • 1:18:19Let me go ahead and define a main function, as before.
    • 1:18:23Let me go ahead and assume, for the moment,
    • 1:18:25that a get_height function exists, which is not a thing in Python.
    • 1:18:28I'm going to invent it in just a moment.
    • 1:18:30And now, I'm going to go ahead and do something like this. for i
    • 1:18:33in the range of that height, well, let's go ahead and print out those hashes.
    • 1:18:39So I'm assuming that get_height exists.
    • 1:18:41Let me go ahead and implement that abstraction, so define a function,
    • 1:18:44now, called get_height.
    • 1:18:46It's not going to take any arguments in this design.
    • 1:18:48While True, I can go ahead and do the same thing as before--
    • 1:18:52assign a variable n, the return value of get_int
    • 1:18:55prompting the user for that height.
    • 1:18:58And then, if n is greater than 0, I can go ahead and break.
    • 1:19:03But if I break here, I, logically-- just like in C--
    • 1:19:08end up executing below the loop in question.
    • 1:19:11But there's nothing there.
    • 1:19:12But if I want get_height to return the height, what should
    • 1:19:16I type here on line 14, logically?
    • 1:19:21What do I want to return, to be clear?
    • 1:19:23AUDIENCE: [INAUDIBLE]
    • 1:19:23DAVID MALAN: Yeah.
    • 1:19:24So I actually want to return n.
    • 1:19:26And here's another curiosity of Python, vis-a-vis C.
    • 1:19:30There doesn't seem to be an issue of scope anymore, right?
    • 1:19:33In C, it was super important to not only declare your variables with the data
    • 1:19:37types, you also had to be mindful of where they exist--
    • 1:19:39inside of those curly braces.
    • 1:19:41In Python, it turns out you can be a little looser with things, for better
    • 1:19:45or for worse.
    • 1:19:45And so, on line 11, if I create a variable called n,
    • 1:19:50it exists on line 11, 12 and even 13, outside of the while loop.
    • 1:19:57So to be clear, in C, with a while loop, we
    • 1:19:59would have ordinarily had not a colon.
    • 1:20:03We would have had the curly brace, like here and over here.
    • 1:20:05And a week ago, I would have claimed that, in C, n
    • 1:20:08does not exist outside of the while loop, by nature of those curly braces.
    • 1:20:12Even though the curly braces are gone, Python actually
    • 1:20:15allows you to use a variable any time after you have assigned it a value.
    • 1:20:20So slightly more powerful, as such.
    • 1:20:23However, I can tighten this up a little bit, logically.
    • 1:20:26And this is true in C. I don't really need to break out of the loop
    • 1:20:30by using break.
    • 1:20:32Recall that or know that I can actually-- once I'm ready to go,
    • 1:20:36I can just return the value I care about, even inside of the loop.
    • 1:20:40And that will have the side effect of breaking me out of the loop
    • 1:20:43and, also, breaking me out of and returning from the entire function.
    • 1:20:46So nothing too new here, in terms of C versus Python, except for this issue
    • 1:20:50with scope.
    • 1:20:51And I, indeed, returned n at the bottom there,
    • 1:20:53just to make clear that n would still exist.
    • 1:20:56So either of those are correct.
    • 1:20:58Now, I just have a Python program that I think
    • 1:21:02is going to allow me to implement this same Mario idea.
    • 1:21:05So let's run python of mario.py.
    • 1:21:07And-- OK, so nothing happened.
    • 1:21:09Python of mario.py.
    • 1:21:13What did I do wrong?
    • 1:21:14AUDIENCE: [INAUDIBLE]
    • 1:21:14DAVID MALAN: Yeah, I have to call main.
    • 1:21:16So, at the bottom of my code, I have to call main here.
    • 1:21:19And this is a stylistic detail that's been subtle.
    • 1:21:22Generally speaking, when you are writing in Python,
    • 1:21:26there's not a CS50 style guide, per se.
    • 1:21:28There's actually a Python style guide that most people adhere to.
    • 1:21:33And in this case, double blank lines between functions is the norm.
    • 1:21:37I'm doing that deliberately, although it might, otherwise, not be obvious.
    • 1:21:41But now that I've called main on line 16, let's run mario.py once more.
    • 1:21:45Aha.
    • 1:21:46Now we see it.
    • 1:21:47Type in 3, and I'm back in business, printing out the values there.
    • 1:21:51Yeah?
    • 1:21:52AUDIENCE: Why do you [INAUDIBLE]?
    • 1:21:54Why can't [INAUDIBLE]?
    • 1:21:56DAVID MALAN: Sure.
    • 1:21:56Why do I need the if condition at all?
    • 1:21:58Why can't I just return n here as by doing return n.
    • 1:22:02Or if I really want to be succinct, I could technically just do this.
    • 1:22:06The only reason I added the if condition is
    • 1:22:09because, if the user types in negative 1, negative 2,
    • 1:22:11I wanted to prompt them again and again.
    • 1:22:13That's all.
    • 1:22:14But that would be totally acceptable, too, if you were OK with that result
    • 1:22:17instead.
    • 1:22:18Well, let me do one other thing here to point out
    • 1:22:21why we are using get_int so frequently.
    • 1:22:23This new training wheel, albeit temporarily.
    • 1:22:26So let me go back to the way it was a moment ago
    • 1:22:28and let me propose, now, to take away get_int.
    • 1:22:32I claimed earlier that, if you're not using get_int,
    • 1:22:35you can just use the input function itself from Python.
    • 1:22:40But that always returns a string, or a str.
    • 1:22:43And so, recall that you have to pass the output of the input function to an int,
    • 1:22:48either on the same line or, if you prefer, on another line, instead.
    • 1:22:51But it turns out what I didn't do was show
    • 1:22:54you what happens if you don't cooperate with the program.
    • 1:22:59So if I run python of mario.py now, works great, even
    • 1:23:02without the get_int function.
    • 1:23:04And I can do it with 4.
    • 1:23:05Still works great.
    • 1:23:06But let me clear my terminal and be difficult, now,
    • 1:23:09as the user and type in "cat" for the height instead.
    • 1:23:11Enter.
    • 1:23:12Now, we see one of those trace backs again.
    • 1:23:14This one is different.
    • 1:23:15This isn't a name error, but, apparently, a value error.
    • 1:23:18And if I ignore the stuff I don't understand,
    • 1:23:20I can see "invalid literal for int with base 10-- "cat.""
    • 1:23:24That's a super cryptic way of saying that C-A-T is not
    • 1:23:27a number in decimal notation.
    • 1:23:29And so, I would seem to have to, somehow, handle this case.
    • 1:23:32And if you want to be more curious, you'll
    • 1:23:34see that this is, indeed, a traceback.
    • 1:23:36And C tends to do this, too, or the debugger would do this for you, too.
    • 1:23:40You can see all of the functions that have
    • 1:23:41been called to get you to this point.
    • 1:23:43So apparently, my problem is, initially, in line 14.
    • 1:23:48But line 14, if I keep scrolling, is uninteresting.
    • 1:23:50It's main.
    • 1:23:51But line 14 leads me to execute line 2, which is, indeed, in main.
    • 1:23:55That leads me to execute line 9, which is in get_height.
    • 1:23:59And so, OK, here is the issue.
    • 1:24:00So the closest line number to the error message
    • 1:24:02is the one that probably reveals the most.
    • 1:24:05Line 9 is where my issue is.
    • 1:24:06So I can't just blindly ask the user for input and, then, convert it to an int
    • 1:24:10if they're not going to give me an int.
    • 1:24:12Now, how do we deal with this?
    • 1:24:13Well, back in problem set two, you might recall
    • 1:24:16validating that the user typed in a number
    • 1:24:18and using a for loop and the like.
    • 1:24:19Well, it turns out, there's a better way to do this in Python,
    • 1:24:22and the semantics are there.
    • 1:24:24If you want to try to convert something to a number that might not actually
    • 1:24:29be a number, turns out, Python and certain other languages
    • 1:24:32literally have a keyword called try.
    • 1:24:35And if only this existed for the past few weeks, I know.
    • 1:24:37But you can try to do the following with your code.
    • 1:24:40What do I want to try to do?
    • 1:24:41Well, I want to try to execute those few lines, except if there's an error.
    • 1:24:46So I can say except if there's a value error-- specifically,
    • 1:24:50the one I screwed up and created a moment ago.
    • 1:24:53And if there is a value error, I can print out an informative message
    • 1:24:56to the user, like "not an integer" or anything else.
    • 1:25:00And what's happening here, now, is literally this operative word, try.
    • 1:25:05Python is going to try to get input and try to convert it to an int,
    • 1:25:09and it's going to try to check if it's greater than 0
    • 1:25:12and then try to return it.
    • 1:25:14Why?
    • 1:25:15Three of those lines are inside of, indented
    • 1:25:17underneath the try block, except if something goes wrong--
    • 1:25:20specifically, a value error happens.
    • 1:25:23Then, it prints this.
    • 1:25:24But it doesn't return anything.
    • 1:25:26And because I'm in a loop, that means it's going to do it again and again
    • 1:25:30and again until the human actually cooperates and gives me
    • 1:25:33an actual number.
    • 1:25:35And so, this, too, is what the world would call pythonic.
    • 1:25:38In Python, you don't, necessarily, rigorously try to validate
    • 1:25:41the user's input, make sure they haven't screwed up.
    • 1:25:43You honestly take a more lackadaisical approach
    • 1:25:46and just try to do something, but catch an error if it happens.
    • 1:25:50So catch is also a term of art, even though it's not a keyword here.
    • 1:25:53Except if something happens, you handle it.
    • 1:25:55So you try and you handle it.
    • 1:25:57You best-effort programming, if you will.
    • 1:25:59But this is baked into the mindset of the Python programming community.
    • 1:26:04So now, if I do python of mario.py and I cooperate, works great as before.
    • 1:26:08Try and succeed.
    • 1:26:093 works.
    • 1:26:104 works.
    • 1:26:11If, though, I try and fail by typing in "cat," it doesn't crash, per se.
    • 1:26:17It doesn't show me an error.
    • 1:26:18It shows me something more user-friendly, like "not an integer."
    • 1:26:20And then, I can try again with "dog."
    • 1:26:22"Not an integer."
    • 1:26:23I can try again with 5.
    • 1:26:24And now, it works.
    • 1:26:26So we won't, generally, have you write much
    • 1:26:28in the way of these try-except blocks, only because they
    • 1:26:30get a little sophisticated quickly.
    • 1:26:33But that is to reveal what the get_int function is doing.
    • 1:26:35This is why we give you the training wheels,
    • 1:26:37so that, when you want to get an int, you
    • 1:26:39don't have to jump through all these annoying hoops to do so.
    • 1:26:41But that's all the library's really doing for you, is just try and except.
    • 1:26:45You won't be left with any training wheels, ultimately.
    • 1:26:48Questions, now, on getting input and trying in this way?
    • 1:26:55Anything at all?
    • 1:26:56Yeah?
    • 1:26:56AUDIENCE: I'm still [INAUDIBLE] try block.
    • 1:27:03DAVID MALAN: Oh, could you put the condition outside of the try block?
    • 1:27:06Short answer, yes.
    • 1:27:07And, in fact, I struggled with this last night
    • 1:27:09when tweaking this example to show the simplest version.
    • 1:27:11I will disclaim that, really, I should only be trying, literally,
    • 1:27:17to do the fragile part.
    • 1:27:18And then, down here, I should be really doing
    • 1:27:21what you're proposing, which is do the condition out here.
    • 1:27:24The problem is, though, that, logically, this gets messy quickly, right?
    • 1:27:27Because except if there's a value error, I want to print out "not an integer."
    • 1:27:31I can't compare n against 0, then, because n doesn't
    • 1:27:33exist because there was an error.
    • 1:27:35So it turns out-- and I'll show you this;
    • 1:27:37this is now the advanced version of Python--
    • 1:27:39there's actually an else keyword you can use in Python
    • 1:27:42that does not accompany if or elif.
    • 1:27:44It accompanies try and except, which I think is weirdly confusing.
    • 1:27:48A different word would have been better.
    • 1:27:50But if you'd really prefer, I could have done this, instead.
    • 1:27:53And this is one of these design things where reasonable people will disagree.
    • 1:27:56Generally speaking, you should only try to do
    • 1:27:58the one line that might very well fail.
    • 1:28:00But honestly, this looks stupid.
    • 1:28:02No, it's just unnecessarily complicated.
    • 1:28:04And so, my own preference was actually the original, which was-- yeah,
    • 1:28:08I'm trying a few extra lines that, really,
    • 1:28:10aren't going to fail, mathematically.
    • 1:28:11But it's just tighter.
    • 1:28:12It's cleaner this way.
    • 1:28:14And here's, again, the sort of arguments you'll
    • 1:28:16start to make yourself as you get more comfortable with programming.
    • 1:28:18You'll have an opinion.
    • 1:28:19You'll disagree with someone.
    • 1:28:20And so long as you can back you argument up, it's pretty reasonable, probably.
    • 1:28:25All right.
    • 1:28:25So how about we, now, take away some piece of magic
    • 1:28:30that's been here for a while.
    • 1:28:31Let me go ahead and delete all of this here.
    • 1:28:33And let me propose that we revisit not that vertical column and the exceptions
    • 1:28:38that might result from getting input, but these horizontal question marks
    • 1:28:42that we saw a while ago.
    • 1:28:43So I want all of those question marks on the same line.
    • 1:28:45And yet, I worry we're about to see a challenge here because print,
    • 1:28:48up until now, has been putting new lines everywhere automatically,
    • 1:28:51even without those backslash n's.
    • 1:28:53Well, let me propose that we do this.
    • 1:28:56for i in the range of 4.
    • 1:28:58If I want four question marks, let me just print four question marks.
    • 1:29:02Unfortunately, I don't think this is correct yet.
    • 1:29:04Let me run python of mario.py.
    • 1:29:06And, of course, this gives me a column instead of the row of question marks
    • 1:29:11that I want.
    • 1:29:12So how do we do this?
    • 1:29:13Well, it turns out, if you read the documentation for the print function,
    • 1:29:17it turns out that print, not surprisingly, perhaps,
    • 1:29:19takes a lot of different arguments, as well.
    • 1:29:22And in fact, if you go to the documentation for it,
    • 1:29:24you'll see that it takes not just positional
    • 1:29:27arguments-- that is, from left to right, separated by commas.
    • 1:29:30It turns out, Python has supports a fancier feature
    • 1:29:32with arguments where you can pass the names of arguments to functions, too.
    • 1:29:36So what do I mean by this?
    • 1:29:38If I go back to VS Code here and I've read the documentation,
    • 1:29:43it turns out that, yes, as before, you can pass multiple arguments to Python,
    • 1:29:48like this.
    • 1:29:49Hello comma David comma Nalan, that will just automatically
    • 1:29:53concatenate all three of those positional arguments together.
    • 1:29:56They're positional in the sense that they literally flow from left to right,
    • 1:29:59separated by commas.
    • 1:30:01But if you don't want to just pass in values like that,
    • 1:30:03you want to actually print out, as I did before, a question mark.
    • 1:30:07But you want to override the default behavior of print
    • 1:30:11by changing the line ending, you can actually do this.
    • 1:30:14You can use the name of an argument that you know exists from the documentation
    • 1:30:18and set it equal to some alternative value.
    • 1:30:22And in fact, even though this looks cryptic,
    • 1:30:24this is how I would override the end of each line, to be quote, unquote.
    • 1:30:30That is nothing because, if you read the documentation,
    • 1:30:32the default value for this end argument-- does someone want to guess--
    • 1:30:37is--
    • 1:30:38is backslash n.
    • 1:30:39So if you read the documentation, you'll se
    • 1:30:41that backslash n is the implied default for this end argument.
    • 1:30:46And so, if you want to change it, you just say end equals something else.
    • 1:30:49And so, here, I can change it to nothing and, now, rerun python of mario.py.
    • 1:30:57And now, they're all in the same line.
    • 1:30:58Now, it looks a little stupid because I made that week
    • 1:31:01one mistake where I still need to move the cursor to the next line.
    • 1:31:04That's just a different problem.
    • 1:31:05I'm just going to go over here and print nothing.
    • 1:31:07I don't even need to print backslash n because, if print automatically
    • 1:31:10gives you a backslash n, just call print with nothing,
    • 1:31:13and you'll get that for free.
    • 1:31:15So let me rerun python of mario.py.
    • 1:31:16And now, it looks a little prettier at the prompt.
    • 1:31:19And to be super clear as to what's going on--
    • 1:31:21suppose I want to make an exclamation here.
    • 1:31:24I could change the backslash n default to an exclamation point,
    • 1:31:27just for kicks.
    • 1:31:28And if I run python of mario.py Again, now, I
    • 1:31:31get this exclamation with question marks and exclamation points, as well.
    • 1:31:36So that's all that's going on here.
    • 1:31:38And this is what's called a named argument.
    • 1:31:40It literally has a name that you can specify when calling it in.
    • 1:31:43And it's different from positional in that you're literally using the name.
    • 1:31:47Let me propose something else, though.
    • 1:31:49And this is why people like Python.
    • 1:31:50There's just cool ways to do things.
    • 1:31:55That's a three-line, verbose way of printing out four question marks.
    • 1:32:00I could certainly take the shortcut and just do this.
    • 1:32:04But that's not really that interesting for anyone,
    • 1:32:06especially if I want to do it a variable number of times.
    • 1:32:08But Python does let you do this.
    • 1:32:10If you want to multiply a character some number of times,
    • 1:32:15not only can you use plus for concatenation,
    • 1:32:18you can use star or an asterisk for multiplication, if you will-- that is,
    • 1:32:23concatenation again and again and again.
    • 1:32:26So if I just print out, quote unquote, "?"
    • 1:32:29times 4, that's actually going to be the tightest way, the most distinct way
    • 1:32:34I can print four question marks instead.
    • 1:32:36And if I don't use 4, I use n, where I get n from the user.
    • 1:32:39Bang.
    • 1:32:39Now, I've gotten rid of the for loop entirely,
    • 1:32:42and I'm using the star operator to manipulate it instead.
    • 1:32:48And, to be super clear here, insofar as Python
    • 1:32:50does not have malloc or free or memory management that you have to do,
    • 1:32:54guess what Python also doesn't have.
    • 1:32:59Anything on your minds in the past couple of week?
    • 1:33:03Doesn't have--
    • 1:33:03AUDIENCE: Pointers.
    • 1:33:04DAVID MALAN: Pointers, yeah.
    • 1:33:06So Python does not have pointers, which just means that all of that
    • 1:33:09happens for you automatically, underneath the hood,
    • 1:33:11again, by way of code that someone else wrote.
    • 1:33:14How about one more throwback with Mario?
    • 1:33:15We've talked about, in week one, this two-dimensional structure where
    • 1:33:20it's like I claim 3 by 3-- a grid of bricks, if you will.
    • 1:33:24Well, how can we do this in Python?
    • 1:33:25We can do this in a couple of ways, now.
    • 1:33:27Let me go back to my mario.py, and let me do something like for i in range
    • 1:33:32of-- we'll just do 3, even though I know, now, I could use get_int
    • 1:33:36or I could use input and int.
    • 1:33:38And if I want to do something two-dimensionally, just like in C,
    • 1:33:41you can nest your for loops.
    • 1:33:42So maybe I could do for j in range of 3.
    • 1:33:45And then, in here, I could print out a hash symbol.
    • 1:33:50And then, let's see if that gives me 9 total.
    • 1:33:53So if I've got a nested loop like this, python of mario.py
    • 1:33:56hopefully gives me a grid.
    • 1:33:58No, it gave me a column of 9.
    • 1:34:01Why, logically, even though I've got my row and my columns?
    • 1:34:09Yeah.
    • 1:34:10AUDIENCE: [INAUDIBLE]
    • 1:34:11DAVID MALAN: Yeah, the line ending.
    • 1:34:13So in my row, I can't let print just keep adding new line, adding new line.
    • 1:34:17So I just have to override this here and let me not screw up like before.
    • 1:34:20Let me print one at the end of the whole row, just to move the cursor down.
    • 1:34:24And I think, now, together, we've got our 3 by 3.
    • 1:34:28Of course, we could tighten this up further.
    • 1:34:29If I don't like the nested loop, I probably could go in here
    • 1:34:33and just print out, for instance, a brick times 3.
    • 1:34:37Or I could change the 3 to a variable if I've gotten it from the user.
    • 1:34:41So I can tighten this up further.
    • 1:34:42So, again, just different ways to solve the same problem and, again, evidence
    • 1:34:45of why a lot of people like Python.
    • 1:34:47There's just some more pleasant ways to solve problems
    • 1:34:49without getting into the weeds, constantly, of doing things,
    • 1:34:52like with for loops and while loops endlessly.
    • 1:34:56All right.
    • 1:34:57Well, how about some other building blocks?
    • 1:34:59Lists are going to be so incredibly useful in Python, just as arrays
    • 1:35:02were in C. But arrays are annoying because you
    • 1:35:04have to manage the memory yourself.
    • 1:35:06You have to in advance how big they are or you
    • 1:35:08have to use pointers and malloc or realloc to resize them.
    • 1:35:11Oh my god.
    • 1:35:12The past two weeks have been painful, in that sense.
    • 1:35:14But Python does this all for free for you.
    • 1:35:17In fact, there's a whole bunch of functions
    • 1:35:19that come with Python that involve lists,
    • 1:35:22and they'll allow us, ultimately, to do things again and again and again
    • 1:35:29within the same data structure.
    • 1:35:30And, for instance, we'll be able to get the length of a list.
    • 1:35:33You don't have to remember it yourself in a variable.
    • 1:35:35You can just ask Python how many elements are in this list.
    • 1:35:39And with this, I think we can solve some old problems, too.
    • 1:35:42So let me go back here, to VS Code.
    • 1:35:45Let me close mario and give us a new program called scores.py.
    • 1:35:50And rather than show the C and the Python now, let's just focus on Python.
    • 1:35:54And in scores.c way back when, we just averaged three test scores or something
    • 1:35:59like that--
    • 1:35:5972, 73, and 33--
    • 1:36:01a few weeks ago.
    • 1:36:03So if I want to create a list in this Python version of 72, 73, 33,
    • 1:36:07I just use my square bracket notation.
    • 1:36:09C let you use curly braces if you know the values in advance,
    • 1:36:12but Python's just this.
    • 1:36:14And now, if I want to compute the average--
    • 1:36:16in C, recall, I did something with a loop.
    • 1:36:19I added all the values together.
    • 1:36:21I, then, divide it by the total number of values
    • 1:36:23just like you would in grade school, and that gave me the average.
    • 1:36:26Well, Python comes with a lot of super handy functions--
    • 1:36:29not just length, but others, as well.
    • 1:36:31And so, in fact, if you want to compute the average,
    • 1:36:34you can take the sum of all of those scores
    • 1:36:36and divide it by the length of all of those scores.
    • 1:36:40So Python comes with length, comes with sum.
    • 1:36:42You can just pass in a whole list of any size
    • 1:36:45and let it deal with that problem for you.
    • 1:36:47So if I want to, now, print out this average,
    • 1:36:49I can print out Average colon--
    • 1:36:51and then, I'll plug in my average variable for interpolation.
    • 1:36:55Let me make this an fstring so that it gets formatted,
    • 1:36:58and let me just run python of scores.py.
    • 1:37:01And there is my average.
    • 1:37:02It's rounding weird because we're still vulnerable to some floating point
    • 1:37:05imprecision, but at least I didn't need loops
    • 1:37:09and I didn't have to write all this darn code just
    • 1:37:11to do something that Excel and Google Spreadsheets can just do like that.
    • 1:37:15Well, Python is closer to those kinds of tools,
    • 1:37:17but more powerful in that you can manipulate the data yourself.
    • 1:37:21How about, though, if I want to get a bunch of scores manually from the user
    • 1:37:25and, then, sum them together.
    • 1:37:27Well, let's combine a few ideas here.
    • 1:37:28How about this?
    • 1:37:29First, let me go ahead and import the get_int function from the CS50 library,
    • 1:37:36just so we don't have to deal with try and except or all of that.
    • 1:37:39And let me go ahead and give myself an empty list.
    • 1:37:42And this is powerful.
    • 1:37:44In C, [SIGHS] there's no point to an empty array
    • 1:37:48because, if you create an empty array with square bracket notation,
    • 1:37:50it's not useful for anything.
    • 1:37:52But in Python, you can create it empty because Python
    • 1:37:55will grow and shrink the list for you automatically, as you add things to it.
    • 1:37:59So if I want to get three scores from the user,
    • 1:38:01I could do something like this-- for i in range of 3.
    • 1:38:04And then, I can grab a variable called "score" or anything.
    • 1:38:08I could call get_int, prompt the human for the score
    • 1:38:11that they want to type in.
    • 1:38:12And then, once they do, I can do this.
    • 1:38:15Thinking back to our object-oriented programming capability now,
    • 1:38:19I could do scores.append, and I can append that score to it.
    • 1:38:24And you would only know this from having read the documentation, heard it
    • 1:38:27in class, in a book or whatnot, but it turns out
    • 1:38:30that, just like strings have functions like lower built into them,
    • 1:38:33lists have functions like append built into them that just literally appends
    • 1:38:37to the end of the list for you, and Python
    • 1:38:40will grow or shrink it as needed.
    • 1:38:42No more malloc or realloc or the like.
    • 1:38:44So this just appends to the scores list.
    • 1:38:49That score, and then again and again and again.
    • 1:38:51So the array starts at--
    • 1:38:52sorry, the list starts at size 0, then grows to 1 then 2 then 3
    • 1:38:57without you having to do anything else.
    • 1:38:59And so, now, down here, I can compute an average
    • 1:39:02with the sum of those scores divided by the length
    • 1:39:05of the total number of scores.
    • 1:39:07And to be clear, length is the total number of elements in the list.
    • 1:39:11Doesn't matter how big the values themselves are.
    • 1:39:14Now I can go ahead and print out an fstring with something
    • 1:39:18like Average colon average in curly braces.
    • 1:39:22And if I run python of scores.py--
    • 1:39:24I'll type in, just for the sake of discussion, the three values,
    • 1:39:27I still get the same answer.
    • 1:39:29But that would have been painful to do in C
    • 1:39:31unless you committed, in advance, to a fixed size array-- which we already
    • 1:39:35decided, weeks ago, was annoying-- or you grew it dynamically
    • 1:39:41using malloc or realloc or the like.
    • 1:39:44All right.
    • 1:39:45What else can I do?
    • 1:39:46Well, there's some nice things you might as well know exist.
    • 1:39:49Instead of scores.append, you can do slight fanciness like this.
    • 1:39:54If you want to append something to a list,
    • 1:39:57you can actually do plus equals, and then
    • 1:40:00put that thing in a temporary list of its own
    • 1:40:03and just use what is essentially concatenation--
    • 1:40:05but not concatenation of strings, but concatenation of lists.
    • 1:40:09So this new line 6 appends to the score's list--
    • 1:40:13this tiny, little list I'm temporarily creating
    • 1:40:15with just the current new score.
    • 1:40:17So just another piece of syntax that's worth seeing that
    • 1:40:20allows you to do something like that, as well.
    • 1:40:23All right.
    • 1:40:23Well, how about we go back to strings for a moment?
    • 1:40:26And all of these examples, as always, are on the course's website afterward.
    • 1:40:29Suppose we want to do something like converting characters to uppercase.
    • 1:40:32Well, to be clear, I could do something like this.
    • 1:40:35Let me create a program called uppercase.py.
    • 1:40:38Let me prompt the user for a before string as by using the input function
    • 1:40:42or get_string, which is almost the same.
    • 1:40:44And I'll prompt the user for a string beforehand.
    • 1:40:47Then, let me go ahead and print out, how about, the keyword "After,"
    • 1:40:52and then end the new line with nothing, just so
    • 1:40:56that I can see "Before" on one line and "After" on the next line.
    • 1:41:00And then, let me do this--
    • 1:41:01and here's where Python gets pleasant, too, with loops--
    • 1:41:04for c in before--
    • 1:41:07print c.upper end equals quote, unquote.
    • 1:41:11And then, I'll print this here.
    • 1:41:12All right.
    • 1:41:13That was fast, but let's try to infer what's going on.
    • 1:41:15So line 1 just gets input from the user, stores it in a variable called before.
    • 1:41:19Line two literally just prints "After" but doesn't
    • 1:41:22move the cursor to the next line.
    • 1:41:25What it, then, does is this.
    • 1:41:27And, in C, this was a little more annoying.
    • 1:41:29You needed a for loop with i.
    • 1:41:31You needed array notation with the square brackets.
    • 1:41:34But, Python, if you say for variable in string--
    • 1:41:39so for c, for character, in string, Python
    • 1:41:42is going to automatically assign c to the first letter
    • 1:41:46that the user types in.
    • 1:41:47Then, on the next iteration, the second letter, the third letter,
    • 1:41:49and the fourth.
    • 1:41:49So you don't need any square bracket notation, you just use c,
    • 1:41:52and Python will do it for you and just hand you back,
    • 1:41:55one at a time, each of the letters that the user has typed in.
    • 1:41:59So if I go back over here and I run, for instance, python of uppercase.py
    • 1:42:04and I'll type in, how about, "david" in all lowercase and hit Enter,
    • 1:42:09you'll now see that it's all uppercase instead by iterating over it,
    • 1:42:13indeed, one character at a time.
    • 1:42:15But we already know, thanks to object-oriented programming,
    • 1:42:17strings themselves have the functionality built
    • 1:42:20in to not just uppercase single characters, but the whole string.
    • 1:42:24So, honestly, this was a bit of a silly exercise.
    • 1:42:26I don't need to use a loop anymore, like in C. And so, some of the habits
    • 1:42:31you've only just developed in recent weeks, it's time to start breaking them
    • 1:42:34when they're not necessary.
    • 1:42:36I can create a variable called after, set it equal to before.upper--
    • 1:42:40which, indeed, exists, just like dot lower exists.
    • 1:42:43And then, what I can go ahead and print out is, for instance--
    • 1:42:47let's get rid of this print line here and do it at the end--
    • 1:42:49"After" and print the value of that variable.
    • 1:42:53So now, if I rerun uppercase.py, type in "david" in all lowercase,
    • 1:42:58I can just uppercase the whole thing all at once because, again, in Python,
    • 1:43:03you don't have to operate on characters individually.
    • 1:43:07Questions on any of these tricks up until now?
    • 1:43:13No?
    • 1:43:13All right.
    • 1:43:14How about a few other techniques that we saw in C that we'll bring back,
    • 1:43:17now, in Python.
    • 1:43:18So it turns out, in Python, there are other libraries you can use, too,
    • 1:43:22that unlock even more functionality.
    • 1:43:24So, in C, if you wanted command line arguments,
    • 1:43:27you just change the signature for main to be, instead of void,
    • 1:43:32int argc comma string argv, open brackets for an array or char star,
    • 1:43:38eventually.
    • 1:43:39Well, it turns out, in Python, that, if you want to access command line
    • 1:43:41arguments, it's a little simpler, but they're tucked away in a library--
    • 1:43:44otherwise known as a module--
    • 1:43:46called sys, the system module.
    • 1:43:49Now, this is similar, in spirit, to the CS50 library,
    • 1:43:51and that's got a bunch of functionality built in.
    • 1:43:53But this one comes with Python itself.
    • 1:43:55So if I want tot create a program like greet.py, in VS Code,
    • 1:43:59here, let me go ahead and do this.
    • 1:44:01From the sys library, let's import argv.
    • 1:44:05And that's just a thing that exists.
    • 1:44:07It's not built into main because there is no main, per se, anymore.
    • 1:44:10So it's tucked away in that library.
    • 1:44:12And now, I can do something like this.
    • 1:44:14If the length of argv equals equals 2, well,
    • 1:44:16let's go ahead and print out something friendly,
    • 1:44:19like hello comma argv bracket 1, and then, close quotes.
    • 1:44:24Else, if the length of argv is not equal to 2,
    • 1:44:28Let's just go ahead and print out hello, world.
    • 1:44:30Now, at a glance, this might look a little cryptic,
    • 1:44:32but it's identical to what we did a few weeks ago.
    • 1:44:35When I run this, python of greet.py, with no arguments,
    • 1:44:39it just says "hello, world."
    • 1:44:40But if I, instead, add a command line argument, like my first name and hit
    • 1:44:46Enter, now, the length of argv is no longer 1.
    • 1:44:49It's going to be 2.
    • 1:44:51And so, it prints out "Hello, David" instead.
    • 1:44:54So the takeaway here is that, whereas in C,
    • 1:44:57argv technically contained the name of your program, like ./hello or ./greet,
    • 1:45:03and then everything the human typed.
    • 1:45:05Python's a little different in that, because we're
    • 1:45:08using the interpreter in this way--
    • 1:45:10technically, when you run python of greet.py, the length of argv is only 1.
    • 1:45:16It contains only greet.py, so the name of the file.
    • 1:45:18It does not unnecessarily contain Python itself
    • 1:45:21because what's the point of that being there, omnipresently?
    • 1:45:24It does contain the number of words that the human typed after Python itself.
    • 1:45:28So argv is length 1 here. argv is length 2 here.
    • 1:45:32And that's why, when it did equal 2, I saw "Hello, David" instead
    • 1:45:35of the default "Hello, world."
    • 1:45:37So same ability to access command line arguments, add these kinds of inputs
    • 1:45:41to your functions, but you have to unlock it
    • 1:45:43by way of using argv instead, in this way.
    • 1:45:47If you want to see all of the words, you could do something like this.
    • 1:45:51Just as-- if we combine ideas, here-- for i in range of, how about, length
    • 1:45:57of argv.
    • 1:45:59Then, I can do this-- print argv bracket i.
    • 1:46:02All right.
    • 1:46:02A little cryptic, but line 3 is just a for loop iterating
    • 1:46:06over the range of length of argv.
    • 1:46:08So if the human types in two words, the length of argv will be 2.
    • 1:46:12So this is just a way of saying iterate over all of the words in argv,
    • 1:46:16printing them one at a time.
    • 1:46:18So python of greet.py, Enter just prints out the name of the program.
    • 1:46:22python of greet.py with David prints out greet.py and, then, David.
    • 1:46:27I can keep running it though with more words,
    • 1:46:29and they'll each get printed one at a time.
    • 1:46:32But what's nice, too, about Python--
    • 1:46:35and this is the point of this exercise-- honestly, this looks pretty cryptic.
    • 1:46:38This is not very pleasant to look at.
    • 1:46:40If you just want to iterate over every word in a list, which argv is,
    • 1:46:46watch what I can do.
    • 1:46:47I can do for arg or any variable name in argv.
    • 1:46:52Let me just, now, print out that argument.
    • 1:46:54I could keep calling it i, but i seems weird when it's not a number.
    • 1:46:56So I'm changing to arg as a word, instead.
    • 1:46:59If I now do python of greet.py, it does this.
    • 1:47:03If I do python of greet.py, David, it does that again.
    • 1:47:06David Malan, it does that again.
    • 1:47:08So this is, again, why Python is just very appealing.
    • 1:47:10You want to do something this many times, iterate over a list?
    • 1:47:13Just say it, and it reads a little more like English.
    • 1:47:15And there's even other fanciness, too, if I may.
    • 1:47:18It's a little stupid that I keep seeing the name of the program, greet.py,
    • 1:47:21so it'd be nice if I could remove that.
    • 1:47:24Python also supports what are called slices of arrays--
    • 1:47:28sorry, slices of lists.
    • 1:47:30Even I get the terminology confused.
    • 1:47:32If argv is a list, then it's going to print out everything in it.
    • 1:47:36But if I want a slice of it that starts at location 1 all the way to the end,
    • 1:47:41you can use this funky syntax in between the square brackets, which
    • 1:47:45we've not seen yet, that's going to start at item 1
    • 1:47:48and go all the way to the end.
    • 1:47:50And so, this is a nice, clever way of slicing off,
    • 1:47:53if you will, the very first element because now,
    • 1:47:56when I run greet.py, David Malan, I should only see David and Malan.
    • 1:48:01If I only want one element, I could do 1 to 2.
    • 1:48:04If I want all of them, I could do 0 onward.
    • 1:48:08I could give myself just one of them in this way.
    • 1:48:10So you can play with the start value and the end value in this way,
    • 1:48:14to slice and dice these lists in different ways.
    • 1:48:17That would have been a pain in C, just because we didn't really
    • 1:48:20have the built-in support for manipulating arrays as cleanly as this.
    • 1:48:26All right.
    • 1:48:27Just so you've seen it, too-- though, this one is less exciting to see live--
    • 1:48:31if I go ahead and create a quick program here, it turns out,
    • 1:48:33there's something else in the sys library, the ability to exit programs--
    • 1:48:37either exiting with status code 1 or 0, as we've been doing any time something
    • 1:48:41goes right or wrong.
    • 1:48:42So, for instance, let me whip up a quick program that just says,
    • 1:48:45if the length of sys.argv does not equal 2, then let's yell at the user
    • 1:48:52and say you're missing a command line argument.
    • 1:48:54Otherwise, command-line argument.
    • 1:48:57And let's, then, return sys.exit(1).
    • 1:49:01Else, let's go ahead and, logically, just say print a formatted string that
    • 1:49:05says hello-- as before--
    • 1:49:07sys.argv 1.
    • 1:49:09Now, things look different all of a sudden,
    • 1:49:11but I'm doing something deliberately.
    • 1:49:13First, let's see what this does.
    • 1:49:14So, on line 1, I'm importing not argv, specifically.
    • 1:49:18I'm importing the whole sys library, and we'll see why in a second.
    • 1:49:22Well, it turns out that the sys library has not only the argv list,
    • 1:49:27it also has a function called exit, which I'd like to be able to use,
    • 1:49:30as well.
    • 1:49:31So it turns out that, if you import a whole library in this way, that's fine.
    • 1:49:35But you have to refer to the things inside of it
    • 1:49:37by using that same library's name and a dot to namespace it, so to speak.
    • 1:49:42So here, I'm just saying, if the user does not type in two words,
    • 1:49:47yell at them with missing command line argument, and then, exit with 1.
    • 1:49:49Just like in C, when you do exit 1, just means something went wrong.
    • 1:49:52Otherwise, print out hello to this.
    • 1:49:54And this is starting to look cryptic, but it's just a combination of ideas.
    • 1:49:57The curly braces means interpolate this value, plug it in here.
    • 1:50:02sys.argv is just the verbose way of saying go into the sys library
    • 1:50:05and get the argv variable therein.
    • 1:50:09And bracket 1, of course, just like arrays in C,
    • 1:50:11is just the second element at the prompt.
    • 1:50:15So when I run this version, now-- python of exit.py--
    • 1:50:18with no arguments, I get yelled at in this way.
    • 1:50:21If, however, I type in two arguments total--
    • 1:50:24the name of the file and my own name--
    • 1:50:26now, I get greeted with hello, David.
    • 1:50:29And it's the same idea before.
    • 1:50:30This was a very low-level technique, but same thing here.
    • 1:50:33If you do echo dollar sign question mark Enter,
    • 1:50:36you'll see the exit code of your program.
    • 1:50:39So if I do this incorrectly again--
    • 1:50:41let me rerun it without my name, Enter--
    • 1:50:43I get yelled at.
    • 1:50:44But if I do echo dollar sign question mark,
    • 1:50:47there's the secret one that's returned.
    • 1:50:50Again, just to show you parity with C, in this case.
    • 1:50:54Questions, now, on any of these techniques, here?
    • 1:50:58No.
    • 1:50:59All right.
    • 1:51:00How about something that's a little more powerful, too?
    • 1:51:02We spend so much time in week 0 and 1 doing searching
    • 1:51:05and, then, eventually, sorting in week 3.
    • 1:51:07Well, it turns out, Python can help with some of this, too.
    • 1:51:10Let me go ahead and create a program called names.py
    • 1:51:12that's just going to be an opportunity to, maybe, search
    • 1:51:15over a whole bunch of names.
    • 1:51:16Let me go ahead and import sys, just so I have access to exit.
    • 1:51:21And let me go ahead and create a variable
    • 1:51:22called names that's going to be a list with a whole bunch of names.
    • 1:51:26How about here?
    • 1:51:27Charlie and Fred and George and Ginny and Percy and, lastly, Ron.
    • 1:51:34So a whole bunch of names here.
    • 1:51:36And it'd be a little annoying to implement
    • 1:51:38code that iterates over that, from left to right, in C, searching for one
    • 1:51:42of those names.
    • 1:51:43In fact, what name?
    • 1:51:43Well, let's go ahead and ask the user to input the name
    • 1:51:46that they want to search for so that we can tell them
    • 1:51:48if the name is there or not.
    • 1:51:50And we could do this, similar to C, in Python, doing something like this.
    • 1:51:54So for n in names, where n is just a variable to iterate over each name--
    • 1:52:00if the name I'm looking for equals the current name in the list--
    • 1:52:05AKA n-- well, let's print out something friendly, like "Found."
    • 1:52:09And then, let's do sys.exit 0 to indicate that we found whoever that is.
    • 1:52:14Otherwise, if we get all the way to the bottom here, outside of this loop,
    • 1:52:17let's just print "Not found" because if we haven't exited yet.
    • 1:52:20And then, let's just exit with 1.
    • 1:52:22Just to be clear, I can continue importing all of sys,
    • 1:52:25or I could do from sys import exit, and then, I could get rid of sys dot
    • 1:52:31everywhere else.
    • 1:52:33But sometimes, it's helpful to know exactly where functions came from.
    • 1:52:36So this, too, is just a matter of style, in this case.
    • 1:52:39All right.
    • 1:52:40So let's go ahead and run this.
    • 1:52:41python of names.py, and let's look for Ron, all the way at the end.
    • 1:52:46All right.
    • 1:52:47He's found.
    • 1:52:47And let's search for someone outside of the family here, like Hermione.
    • 1:52:51Not found.
    • 1:52:52OK.
    • 1:52:53So it seems to be working in this way.
    • 1:52:54But I've essentially implemented what algorithm?
    • 1:52:58What algorithm would this seem to be, per line 7 and 8 to 9 and 10?
    • 1:53:05AUDIENCE: Linear.
    • 1:53:05DAVID MALAN: Yeah.
    • 1:53:06So it's just linear search.
    • 1:53:07It's a loop, even thought he syntax is a little more succinct today,
    • 1:53:10and it's just iterating over the whole thing.
    • 1:53:12Well, honestly, we've seen an even more terse way to do this in Python.
    • 1:53:15And this, again, is what makes it a more pleasant language, sometimes.
    • 1:53:19Why don't I just do this?
    • 1:53:20Instead of iterating one at a time, why don't I just say this?
    • 1:53:24Let me go ahead and change my condition to just
    • 1:53:27be-- how about if the name we're looking for is in the names list, we're done.
    • 1:53:33We found it.
    • 1:53:33Use the end preposition that we've seen a couple of times,
    • 1:53:36now, that itself asks the question, is something in something else?
    • 1:53:40And Python will take care of linear search for us.
    • 1:53:44And it's going to work exactly the same if I
    • 1:53:46do python of names.py, search for Ron.
    • 1:53:48It's still going to find him and it's still
    • 1:53:50going to do it linearly, in this case.
    • 1:53:51But I don't have to write all of the lower-level code myself, in this case.
    • 1:53:58Questions, now, on any of this?
    • 1:54:02The code's just getting shorter and shorter.
    • 1:54:05No?
    • 1:54:05What about-- let's see.
    • 1:54:07What else might we have here?
    • 1:54:09How about this?
    • 1:54:10Let's go ahead and implement that phonebook
    • 1:54:12that we started, metaphorically, with in the beginning of the course.
    • 1:54:15Let's code up a program called phonebook.py.
    • 1:54:17And in this case, let's go ahead and let's create a dictionary this time.
    • 1:54:22Recall that a dictionary is a little something that
    • 1:54:25implements something like this--
    • 1:54:27a two-column table that's got keys and values, words
    • 1:54:31and definitions, names and numbers.
    • 1:54:33And let's focus on the last of those, names and numbers, in this case.
    • 1:54:36Well, I claimed earlier that Python has built-in support
    • 1:54:38for dictionaries-- dict objects-- that you can create with one line.
    • 1:54:42I didn't need it for speller because a set is sufficient
    • 1:54:45when you only want one of the keys or the values, not both.
    • 1:54:47But now, I want some names and numbers.
    • 1:54:49So it turns out, in Python, you can create an empty dictionary
    • 1:54:53by saying dict open parenthesis, closed.
    • 1:54:55And that just gives you, essentially, a chart that
    • 1:54:58looks like this, with nothing in it.
    • 1:54:59Or there's more succinct syntax.
    • 1:55:01You can, alternatively, do this, with two curly braces, instead.
    • 1:55:06And, in fact, I've been using a shortcut all this time.
    • 1:55:09When I had a list, earlier, where my variable was called scores,
    • 1:55:15and I did this, that was actually the shorthand version of this--
    • 1:55:19hey, Python, give me an empty list.
    • 1:55:21So there's different syntax for achieving the same goal.
    • 1:55:23In this case, if I want a dictionary for people,
    • 1:55:27I can either do this or, more commonly, just two curly braces, like that.
    • 1:55:32All right.
    • 1:55:33Well, what do I want to put in this?
    • 1:55:34Well, let me actually put some things in this.
    • 1:55:36And I'm going to just move my closed curly brace to a new line.
    • 1:55:39If I want to implement this idea of keys and values,
    • 1:55:42the way you do this in Python is key colon value comma.
    • 1:55:47Key colon value.
    • 1:55:48So you'd implement it more in code.
    • 1:55:50So, for instance, if I want Carter to be the first key in my phone book and I
    • 1:55:54want his number to be +1-617-495-1000, I can put that as the corresponding
    • 1:56:00value.
    • 1:56:00The colon is in between.
    • 1:56:02Both are strings, or strs, so I've quoted both deliberately.
    • 1:56:05If I want to add myself, I can put a comma.
    • 1:56:07And then, just to keep things pretty, I'm moving the cursor to the next line.
    • 1:56:10But that's not strictly required, aesthetically.
    • 1:56:12It's just good style.
    • 1:56:13And here, I might do +1-949-468-2750.
    • 1:56:19And now, I have a dictionary that, essentially, has two rows, here--
    • 1:56:24Carter and his number and David and his number, as well.
    • 1:56:27And if I kept adding to this, this chart would just get longer and longer.
    • 1:56:30Suppose I want to search for one of our numbers.
    • 1:56:32Well, let's prompt the user for the name,
    • 1:56:34for whose number you want to search by getting string.
    • 1:56:37Or you know what?
    • 1:56:38We don't need this CS50 library.
    • 1:56:39Let's just use input and prompt the user for a name.
    • 1:56:43And now, we can use this super terse syntax and just say if name in people,
    • 1:56:49print the formatted string number colon and--
    • 1:56:53here, we can do this-- people bracket name.
    • 1:56:57OK.
    • 1:56:57So this is getting cool quickly, confusingly.
    • 1:57:01So let me run this.
    • 1:57:02python of phonebook.py Let's type in Carter.
    • 1:57:06And, indeed, I see his number.
    • 1:57:08Let's run it again with David, and I see my number here.
    • 1:57:12So what's going on?
    • 1:57:14Well, it turns out that a dictionary is very similar, in spirit, to a list.
    • 1:57:19It's actually very similar, in spirit, to an array in C.
    • 1:57:22But instead of being limited to keys that are numbers, like bracket 0,
    • 1:57:27bracket 1, bracket 2, you can actually use words.
    • 1:57:30And that's all I'm doing here on line 8.
    • 1:57:33If I want to check for the name Carter, which is currently
    • 1:57:36in this variable called name, I can index
    • 1:57:39into my people dictionary using not a number,
    • 1:57:42but using, literally, a string--
    • 1:57:44the name Carter or David or anything else.
    • 1:57:48To make this clearer, too, notice that I'm, at the moment,
    • 1:57:50using this format string, which is adding some undue complexity.
    • 1:57:54But I could clarify this, perhaps, further as this.
    • 1:57:56I could give myself another variable called
    • 1:57:58number, set it equal to the people dictionary,
    • 1:58:01indexing into it using the current name.
    • 1:58:03And now, I can shorten this to make it clearer that all I'm doing
    • 1:58:07is printing the value of that.
    • 1:58:09And, in fact, I can do this even more cryptically.
    • 1:58:12This would be weird to do, but if I only ever want to show David's phone number
    • 1:58:16and never Carter's, I can literally, quote unquote, "index into" the people
    • 1:58:21dictionary because, now, when I run this, even if I type Carter,
    • 1:58:24I'm going to get back my number instead.
    • 1:58:27But that's all that's happening if I undo that, because that's now a bug.
    • 1:58:31But I index into it using the value of name.
    • 1:58:35Dictionaries are just so wonderfully convenient
    • 1:58:37because, now, you can associate anything with anything else
    • 1:58:39but not using numbers, but entire key words, instead.
    • 1:58:43So here's how, if, in speller, we gave you not just words,
    • 1:58:46but hundreds of thousands of definitions, as well,
    • 1:58:50you could essentially store them as this.
    • 1:58:52And then, when the human wants to look up a definition in a proper dictionary,
    • 1:58:55not just for spell checking, you could index
    • 1:58:57into the dictionary using square brackets
    • 1:59:00and get back the definition in English, as well.
    • 1:59:04Questions on this?
    • 1:59:06Yeah?
    • 1:59:07AUDIENCE: Is the way this code does, as presented,
    • 1:59:09saying that Python has [INAUDIBLE]?
    • 1:59:21DAVID MALAN: A really good question.
    • 1:59:22So, to summarize, how is Python finding that name within that dictionary?
    • 1:59:27This is where, honestly, speller in p-set 5 is what Python's all about.
    • 1:59:31So you have struggled, are struggling with implementing your own spell
    • 1:59:34checker and implementing your own hash table.
    • 1:59:36And recall that, per last week, the goal of a hash table is to,
    • 1:59:39ideally, get constant time access.
    • 1:59:41Not something linear, which is slow and even better than something logarithmic,
    • 1:59:45like log base 2 of n.
    • 1:59:47So Python and the really smart people who invented it,
    • 1:59:50they have written the code that does its best to give you
    • 1:59:53constant time searches of dictionaries.
    • 1:59:55And they're not always going to succeed, just as you
    • 1:59:58and your own problem set are probably going
    • 1:59:59to have some collisions once in a while and start to have
    • 2:00:01chains of length lists of words.
    • 2:00:03But this is where, again, you defer to someone else, someone
    • 2:00:05smarter than you, someone with more time than you
    • 2:00:07to solve these problems for you.
    • 2:00:09And if you read Python's documentation, you'll
    • 2:00:11see that it doesn't guarantee constant time,
    • 2:00:13but it's going to, ideally, optimize the data structure
    • 2:00:15for you to get as fast as possible.
    • 2:00:19And of all of the data structures like a dictionary,
    • 2:00:22a hash table is, really, like the Swiss army knife of computing
    • 2:00:25because it just lets you associate something with something else.
    • 2:00:28And even though we keep focusing on names and numbers,
    • 2:00:30that's a really powerful thing because it's
    • 2:00:32more powerful than lists and arrays, which
    • 2:00:34are only numbers and something else.
    • 2:00:35Now, you can have any sorts of relationships, instead.
    • 2:00:38All right.
    • 2:00:39Let me show a few other examples before we
    • 2:00:41culminate with some more powerful techniques in Python,
    • 2:00:43thanks to libraries.
    • 2:00:45How about this problem we encountered in week 4, which was this.
    • 2:00:49Let me code up a program called, again, compare.py here but, this time,
    • 2:00:54compare to strings and not numbers.
    • 2:00:56So let me, for instance, get one string from the user called s.
    • 2:01:01Just for the sake of discussion, let me get another string from the user
    • 2:01:04called t so that we can actually do some comparison here.
    • 2:01:07And if s equals equals t, let's go ahead and print out that they're the same.
    • 2:01:12Else, let's go ahead and print out that they're different.
    • 2:01:15So this is very similar to what we did in week 4.
    • 2:01:17But in week 4, recall we did this specifically
    • 2:01:20because we had encountered a problem.
    • 2:01:23For instance, if I run-- whoops.
    • 2:01:28If I run-- what's going on?
    • 2:01:34[INAUDIBLE] Come on.
    • 2:01:40Oh.
    • 2:01:41OK.
    • 2:01:41Wow, OK.
    • 2:01:43Long day.
    • 2:01:43All right.
    • 2:01:44If I run the proper command, python of compare.py, then let's go ahead
    • 2:01:48and type in something like "cat" in all lowercase, "cat" in all lowercase.
    • 2:01:53And they're the same.
    • 2:01:56If, though, I do this again with "dog" and "dog," they're the same.
    • 2:01:59And, of course, "cat" and "dog," they're different.
    • 2:02:01But does anyone recall, from two weeks ago, when I typed in my name twice,
    • 2:02:06both identically capitalized.
    • 2:02:08What did it say?
    • 2:02:10That they were, in fact, different.
    • 2:02:13And why was that?
    • 2:02:14Why were two strings in C different, even though I typed literally
    • 2:02:16the same thing?
    • 2:02:20Two different places in memory.
    • 2:02:21So each string might look the same, aesthetically, but, of course,
    • 2:02:24was stored elsewhere in memory.
    • 2:02:25And yet, Python appears to be using the equality operator--
    • 2:02:29equals equals-- like you and I would expect, as humans-- actually
    • 2:02:33comparing for us char by char in each of those strings for actual [? quality. ?]
    • 2:02:38So this is a feature of Python, in that it's just easier to do.
    • 2:02:41And why?
    • 2:02:42Well, this derives from the reality that, in Python, there
    • 2:02:44are no pointers anymore.
    • 2:02:45There's no underlying memory management.
    • 2:02:47It's not up to you, now, to worry about those lower-level details.
    • 2:02:50The language itself takes care of that for you.
    • 2:02:52And so, similarly, if I do this and don't
    • 2:02:55ask the user for two strings, but just one,
    • 2:02:57and then, I do something like this.
    • 2:02:59How about give myself a second variable t, set it equal to s.capitalize, which,
    • 2:03:05note, is not the same as upper; capitalize, by design,
    • 2:03:08per Python's documentation, will only capitalize the first letter for you--
    • 2:03:12I can now print out, say, two fstrings here--
    • 2:03:15what the value of s is and, then, let me print out,
    • 2:03:18with another fstring, what the value of t is.
    • 2:03:20And recall that, in C, this was a problem
    • 2:03:22because if you capitalize s and store it in t,
    • 2:03:26we accidentally capitalized both s and t.
    • 2:03:29But in this case, in Python, when I actually run this and type in "cat"
    • 2:03:33In all lowercase, the original s is unchanged
    • 2:03:37because, when I use capitalize on line 3, this is, indeed, capitalizing s.
    • 2:03:42But it's returning a copy of the result. It cannot change s itself
    • 2:03:47because, again, for that technical term, s is immutable.
    • 2:03:50Strings, once they exist, cannot be changed themselves.
    • 2:03:53But you can return copies and modify mutated copies of those same strings.
    • 2:03:58So, in short, all of those headaches we encountered in week 4
    • 2:04:02are now solved, really, in the way you might expect.
    • 2:04:05And here's another one that we dwelled on in week 4,
    • 2:04:07with the colored liquid in glasses.
    • 2:04:09Let me code up a program called swap.py.
    • 2:04:12And in swap.py, let me set x equal to 1, y equal to 2.
    • 2:04:16And then, let me just print out an fstring here.
    • 2:04:18So how about x is this comma y is that.
    • 2:04:24And then, let me do that twice, just for the sake of demonstration.
    • 2:04:27And in here, recall that we had to create a swap function.
    • 2:04:31But then, we had to pass it in by reference with the ampersand.
    • 2:04:33And oh my god, that was peak complexity in C. Well,
    • 2:04:38if you want to swap x and y in Python, you
    • 2:04:41could do x comma y equals y comma x.
    • 2:04:43And now, python of swap.py.
    • 2:04:49And there we go.
    • 2:04:50All of that's handled for you.
    • 2:04:51It's like a shell game without even a temporary variable in mind.
    • 2:04:56So what more can we do here?
    • 2:04:58How about a few final building blocks?
    • 2:05:00And these related, now, to files from that week 4.
    • 2:05:03Suppose that I want to save some names and numbers in a CSV file--
    • 2:05:07Comma Separated Values, which is like a very lightweight spreadsheet.
    • 2:05:11Well, first, let me create a phonebook.csv file
    • 2:05:15that just has name comma number as the first row there.
    • 2:05:19But after that, I'm going to go ahead, now, and code up
    • 2:05:21a phonebook.py program that actually allows
    • 2:05:25me to add things to this phonebook.
    • 2:05:27So let me split my screen here so that we can see the old and the new.
    • 2:05:31And down here, in my code for phonebook.py,
    • 2:05:34in this new and improved version, I'm going
    • 2:05:36to actually import a whole other library, this one called CSV.
    • 2:05:40And here, too, especially for people in data science and the like,
    • 2:05:42really like being able to manipulate files and data that might very well be
    • 2:05:46stored in spreadsheets or CSVs--
    • 2:05:48Comma Separated Values, which we saw briefly in week 4.
    • 2:05:51In phonebook.py, then, it suffices to just
    • 2:05:53import CSV after reading the documentation therefore
    • 2:05:57because this is going to give me functionality
    • 2:05:59in code related to CSV files.
    • 2:06:02So here's how I might open a file in Python.
    • 2:06:04I literally call open-- it's not fopen now; it's just open--
    • 2:06:08and I open this file called phonebook.csv.
    • 2:06:10And just as in C, I'm going to open it in append mode--
    • 2:06:13not right, where it would change the whole thing.
    • 2:06:15I want to append new line at a time.
    • 2:06:18After this, I want to get, maybe, a name from the user.
    • 2:06:21So let's prompt the user for some input for their name.
    • 2:06:25And then, let's prompt the user for a number,
    • 2:06:27as well, using input prompting for number.
    • 2:06:31All right.
    • 2:06:31And now, this is a little cryptic, and you'd only
    • 2:06:33know this from the documentation.
    • 2:06:35But if you want to write rows to a CSV file
    • 2:06:38that you can, then, view in Excel or the like, you can do this--
    • 2:06:41give me a variable called writer-- but I could call it anything I want.
    • 2:06:45Let me use a csv.writer function that comes with this CSV library,
    • 2:06:50passing in the file.
    • 2:06:51This is like saying, hey, Python, treat this open file as a CSV file
    • 2:06:56so that things are separated with commas and nicely formatted
    • 2:06:59in rows and columns.
    • 2:07:00Now, I'm going to do this--
    • 2:07:02use that writer to write a row.
    • 2:07:04Well, what do I want to write?
    • 2:07:05I want to write a short list--
    • 2:07:07namely, the current name and the current number--
    • 2:07:10to that file, but I don't want to use fprintf and %s and all of that stuff
    • 2:07:14that we might have had in the past.
    • 2:07:16And now, I just want to close the file.
    • 2:07:19Let me reopen my terminal.
    • 2:07:20Let me run python of phonebook.py, and let me type in David and then
    • 2:07:26+1-949-468-2750 and, crossing my fingers,
    • 2:07:30watching the actual CSV at top-left.
    • 2:07:33My code has just added me to the file.
    • 2:07:35And if I were to run it again, for instance,
    • 2:07:37with Carter and +1-617-495-1000, crossing my fingers again--
    • 2:07:41we've updated the file.
    • 2:07:42And it turns out, there's code now, via which I can even read that file.
    • 2:07:46But I can, first, tighten this up, just so you've seen it.
    • 2:07:48It turns out, in Python, it's so common to open files and close them.
    • 2:07:52Humans make mistakes, and they often forget
    • 2:07:54to close files, which might, then, end up using more memory than you intend.
    • 2:07:58So you can, alternatively, do this in Python
    • 2:08:00so that you don't have to worry about closing files.
    • 2:08:03You can use this keyword instead.
    • 2:08:05You can say with the opening of this file
    • 2:08:09as a variable called file do all of the following underneath.
    • 2:08:13So I'm indenting most of my code.
    • 2:08:15I'm using this new, Python-specific keyword called width.
    • 2:08:18And this is just a matter of saying, with the following opening of the file,
    • 2:08:22do those next four lines of code, and then, automatically close it for me
    • 2:08:26at the end of the indentation.
    • 2:08:27It's a minor optimization, but this, again, is the pythonic way
    • 2:08:31to do things, instead.
    • 2:08:33How else might I do this, too?
    • 2:08:34Well, it turns out that the code I've written here-- on line 9,
    • 2:08:38especially-- is a little fragile.
    • 2:08:40If any human opens this spreadsheet-- the CSV file in Excel,
    • 2:08:44Google Spreadsheets, Apple Numbers--
    • 2:08:46and maybe moves the columns around just because, maybe, they're fussing.
    • 2:08:49They saved it, and they don't realize they've, now, changed my assumptions.
    • 2:08:52I don't want to, necessarily, write name and number
    • 2:08:55always in that order because what if someone screws up and flips those two
    • 2:08:58columns by literally dragging and dropping?
    • 2:09:01So it turns out that, instead of using a list here,
    • 2:09:03we can use another feature of this library, as follows.
    • 2:09:06Instead of using a writer, there's something
    • 2:09:09called a dictionary writer or dict writer
    • 2:09:11that takes the same argument as input--
    • 2:09:14the file that's opened.
    • 2:09:15But now, the one difference here is that you
    • 2:09:18need to tell this dictionary writer that your field names are name and number.
    • 2:09:25And let me close the CSV here.
    • 2:09:27Name and number are the names of the fields, the columns in this CSV file.
    • 2:09:32And when it comes time to write a new row,
    • 2:09:34the syntax here is going to be a little uglier, but it's just a dictionary.
    • 2:09:37The name I want to write to the dictionary
    • 2:09:40is going to be whatever name the human typed in.
    • 2:09:42The number that I want to write to the CSV file
    • 2:09:45is going to be whatever the number the human typed in.
    • 2:09:48But what's different, now, about this code is,
    • 2:09:51by simply using a dictionary writer here instead of the generic writer,
    • 2:09:55now, the columns can be in this order or this order or any order.
    • 2:10:00And the dictionary writer is going to figure out,
    • 2:10:03based on the first line of text in that CSV, where to put name,
    • 2:10:06where to put number.
    • 2:10:07So if you flip them, no big deal.
    • 2:10:08It's going to notice, oh, wait, the columns changed.
    • 2:10:11And it's going to insert the columns correctly.
    • 2:10:14So just, again, another more powerful feature that lets you
    • 2:10:18focus on real work, as opposed to actually getting
    • 2:10:22tied up in the weeds of writing code like this, otherwise.
    • 2:10:27Questions on this one, as well?
    • 2:10:30But what we will do, now, is come full circle
    • 2:10:33to some of the more sophisticated examples with which we began,
    • 2:10:37and I'm going to go back over to my own Mac laptop
    • 2:10:40here, where I've got my own terminal window up and running,
    • 2:10:43and I was just going to introduce a couple of final libraries
    • 2:10:46that really speak to just how powerful Python can be
    • 2:10:49and how quickly you can get up and running.
    • 2:10:51To be fair, can't necessarily do all of these things in the cloud,
    • 2:10:54like in code spaces, because you need access to your own speakers
    • 2:10:57or microphone or the like.
    • 2:10:58So that's why I'm doing it on my own Mac, here.
    • 2:11:01But let me go ahead and open up a program called speech.py.
    • 2:11:05And I'm not using VS Code here.
    • 2:11:07I'm using a program called VI that's entirely terminal window based.
    • 2:11:10But it's going to allow me, for instance, to import the Python
    • 2:11:13text to speech version 3 library.
    • 2:11:16I'm going to give myself a variable called engine that's
    • 2:11:18going to be set equal to the Python text to speech
    • 2:11:213 libraries init method, which is just going to initialize this library that
    • 2:11:26relates to text to speech.
    • 2:11:28I'm going to, then, use the engine's say function to say something
    • 2:11:32like, how about, hello comma world.
    • 2:11:35And then, as my last line, I'm going to say engine.runAndWait, capitalized
    • 2:11:39as such, to tell my program, now, to run that speech and wait until it's done.
    • 2:11:44All right.
    • 2:11:45I'm going to save this file.
    • 2:11:46I'm going to run python of speech.py.
    • 2:11:49And I'm going to cross my fingers, as always, and--
    • 2:11:52INTERPRETER: Hello, world.
    • 2:11:53DAVID MALAN: All right.
    • 2:11:54So now, I have a program that's actually synthesizing speech
    • 2:11:57using a library like this.
    • 2:11:58How can I, now, modify this to be a little more interesting?
    • 2:12:01Well, how about this?
    • 2:12:02Let me go ahead and prompt the user for their name,
    • 2:12:05like we've done several times here, using Python's built-in name function.
    • 2:12:08And now, let me go ahead and use a format string in conjunction
    • 2:12:11with this library, interpolating the value of name there.
    • 2:12:14And-- at least, if my name is somewhat phonetically pronounceable--
    • 2:12:18let's go ahead and run python of speech.py, type in my name, and--
    • 2:12:23INTERPRETER: Hello, David.
    • 2:12:24DAVID MALAN: OK.
    • 2:12:25It's a weird choice of inflection, but we're
    • 2:12:27starting to synthesize voice, not unlike Siri or Google Assistant
    • 2:12:30or Alexa or the like.
    • 2:12:32Now, we can, maybe, do something a little more advanced, too.
    • 2:12:36In addition to synthesizing speech in this way,
    • 2:12:39we could synthesize, for instance, an actual graphic.
    • 2:12:43Let me go ahead, now, and do something like this.
    • 2:12:45Let me create a program called qr.py.
    • 2:12:48I'm going to go ahead and import a library called
    • 2:12:50OS, which gives you access to operating system related functionality in Python.
    • 2:12:54I'm going to import a library I've pre-installed
    • 2:12:56called qrcode, which is a two-dimensional barcode that you
    • 2:12:59might have seen in the real world.
    • 2:13:01I'm going to go ahead and create an image variable using
    • 2:13:03this qrcode library's make function, which, per its documentation,
    • 2:13:08takes a URL, like one of CS50's own videos.
    • 2:13:10So we'll do this with youtu.be/xvF2joSPgG0.
    • 2:13:23So, hopefully, that's the right lecture.
    • 2:13:24And now, we've got img.save, which is going to allow
    • 2:13:27me to create a file called qr.ping.
    • 2:13:30Think back, now, on problem set 4 and how painful it was to save files.
    • 2:13:33We'll just use the save function, now, in Python and save this as a PNG file--
    • 2:13:36Portable Network Graphic.
    • 2:13:38And then, lastly, let's just go ahead and open with the command open qr.png
    • 2:13:43on my Mac so that, hopefully, this just automatically opens.
    • 2:13:46All right.
    • 2:13:46I'm going to go ahead and just double-check my syntax here
    • 2:13:49so that I haven't made any mistakes.
    • 2:13:51I'm going to go ahead and run python of qr.py.
    • 2:13:54Enter.
    • 2:13:55That opens up this.
    • 2:13:57Let me go ahead and zoom in.
    • 2:13:58If you've got a phone handy and you'd like to scan this code here,
    • 2:14:03whether in person or online--
    • 2:14:07I apologize.
    • 2:14:08You won't appreciate it.
    • 2:14:11Amazing!
    • 2:14:12OK.
    • 2:14:13And, lastly, let me go back into our speech example
    • 2:14:17here, create a final ending here in our final moments.
    • 2:14:21And how about we just say something like "This was CS50," like this.
    • 2:14:26Let's go ahead, here.
    • 2:14:27Fix my capitalization, just for tidiness.
    • 2:14:28Let's get rid of the name.
    • 2:14:29And now, with our final flourish and your introduction to Python equipped--
    • 2:14:33here we go--
    • 2:14:35INTERPRETER: This was CS50.
    • 2:14:36DAVID MALAN: All right.
    • 2:14:37We'll see you next time.
    • 2:14:38[APPLAUSE]
    • 2:14:41[MUSIC PLAYING]
  • CS50.ai
Shortcuts
Before using a shortcut, click at least once on the video itself (to give it "focus") after closing this window.
Play/Pause spacebar or k
Rewind 10 seconds left arrow or j
Fast forward 10 seconds right arrow or l
Previous frame (while paused) ,
Next frame (while paused) .
Decrease playback rate <
Increase playback rate >
Toggle captions on/off c
Toggle mute m
Toggle full screen f or double-click video