Free YouTube Transcribe

Video transcript

CS50P - Lecture 4 - Libraries

CS50 · 14,689 words · 67 min read

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

Open in the transcript tool

Full transcript

Introduction

0:00[MUSIC PLAYING]

0:23DAVID MALAN: All right, this is CS50, Introduction

Libraries

0:27to Programming with Python.

0:28My name is David Malan, and this is our week on library.

0:31So libraries are generally files of code that other people

0:35have written that you can use in your own programs or a library's code

0:39that you've written that you can use in your own program,

0:41but maybe not just this program, but another and another as well.

0:45So Python supports exactly this idea.

0:47This ability to share code with others, share code across your own projects.

0:51And it does so by way of what it calls module.

Modules

0:54A module in Python is just a library that

0:57typically has one or more functions or other features built into it.

1:01Generally, the purpose of a library or a module

1:03specifically is to encourage reusability of code

1:06if you find yourself using the same types of functions again and again,

1:10the same functionality.

1:11If you find yourself copying and pasting from an old project

1:15into your new project, odds are there's an opportunity there to factor out

1:20that code that you keep copying and pasting that you keep reusing and put

1:24it into a library that you can then load into your programs moving forward

1:28so as to not just copy and paste it and have

1:30all these different copies all over.

1:32So what are some of the modules or libraries that Python comes with?

1:36Well, Python comes with a random library literally,

1:39which is to say that when you install the Python

1:41interpreter on your Mac or PC or somewhere

1:44in the cloud, not only do you get Python,

1:46you get a whole bunch of modules as well.

1:48Now, these modules provide you with functions

1:50that you don't have access to just by default like you do print and input.

1:54Print and input and other such functions just work in Python.

1:58But sometimes functions are tucked away in these modules,

2:02so you have to be more deliberate about loading them

2:04into the computer's memory.

2:06So somewhere on the computer's hard drive, once you've installed Python,

2:09there is also, it turns out a file, probably called random.py

2:13that someone else wrote probably long ago but that you have access to.

2:17And in that random.py file, there's probably one or more functions

2:20that you yourself can use in order to do things randomly.

2:25That is to say how could you flip a coin in a program in Python?

2:29How could you pick a random number between 1 and 10 in Python?

2:33Well, you need a bit of randomness.

2:34And while you could figure out mathematically

2:37how to write functions like that yourself,

2:39it's a lot easier to stand on the shoulders of others who've already

2:42solved that problem for you so you can focus on the problem

2:45that you yourself want to solve.

2:48So for documentation on most any Python module,

2:51you go to the official Python docs.

2:52And you go to a URL like this where the documentation for that specific module

2:57lives.

2:57And within the documentation, you'll see a list

2:59of the functions or other functionality that some module provide.

3:03But how do you go about loading a module into your own program

3:08so that you can use the functions in that module?

3:10Well, we need a new keyword in Python and namely it's import.

import

3:14The import keyword in Python allows you to import the contents of the functions

3:20from some module in Python.

3:23Well, how might I go about using this in practice?

3:26Well, let me propose that there exists in that random module

3:29this function among others.

3:31So I have copied and pasted from the documentation

3:34this summary of a function called Choice.

3:38Now, the function exists in the random module, so to speak,

3:42not a random module, the random module.

3:45And so generally the documentation describes it fully like this.

3:48random.choice is how you would technically call this function,

3:52though, we'll see alternatives to that.

3:54In parentheses, there is a parameter called S-E-Q for sequence.

3:58And sequence generally means a list or something

4:01that is list-like if you have a list of numbers or strings or anything else.

4:05And the documentation elaborate.

4:06Well, how can I go about using this function to solve, perhaps,

4:09a familiar problem?

4:11Well, let me go ahead and open up VS Code here.

4:13And let me propose that we implement a program that simulates flipping a coin.

4:17A coin that in the US has heads or tails, the idea of which

4:21is to pick a decision with 50/50 probability.

4:2550% probability of heads, 50% probability of tails.

4:29Or you can use some other mechanism like that.

4:31Well, let me go ahead and open a program with code called generate.py

4:35because I want to start generating a whole bunch of random information.

4:39The first of which is just going to be a coin toss.

4:41Now, how do I go about using that function?

4:43Well, I first have to import the random library.

4:46So literally the first or among the first lines of my file

4:49should be import random.

4:51And that just gives me access to all of the functions in that specific module.

4:56Now, suppose I want to flip a coin.

4:58Well, I can do random.choice per the documentation a moment ago.

5:03And that again takes a sequence.

5:05What's a sequence?

5:05It's a list or something that's list-like.

5:07And we know about lists.

5:08We've used lists to iterate over numbers.

5:11We've used lists to iterate over students at Hogwarts.

5:13Let's go ahead now and iterate over just a list of two sides of a coin,

5:18"heads," quote, unquote, or tails.

5:20Now, I could call these anything I want.

5:22These are my string.

5:23I just want to simulate a tossing a coin.

5:25So I'm just going to say in all lowercase, heads and tail.

5:28But notice the syntax.

5:30I have "heads" and "tails" in double quotes.

5:32That's because they're strings.

5:33I could also use single quotes so long as I'm consistent.

5:36There's a comma between them, which means the list has two elements.

5:38They're square brackets to the right and the left, which

5:42indicates that this is indeed a list.

5:44That's the syntax recall for defining a list in Python.

5:47And then lastly, there's something more familiar.

5:49There's the parentheses outside of those square brackets.

5:52But those are just the parentheses that belong to the Choice function

5:55and specify where its parameter gets passed in.

5:58But again, unlike past function, I have to specify what module

6:03this function is in at least for now.

6:05And so I do random.choice to call the specific function.

6:09All right, well, it's one thing to flip a coin picking between those

6:12with 50% probability.

6:14And that's what random.choice does.

6:15It takes in a list, and it returns to one of those values randomly

6:19with equal probability.

6:21Because I've passed in two items, I've got a 50/50 chance.

6:24If I passed in three items, it'd be a 33% chance for each of those items

6:28and so forth.

6:29Python does the math for you.

6:30But I want to store the value of this in a variable.

6:33So let's define a variable called coin equals whatever the return value is.

6:37So this is indeed like flipping a coin.

6:39I'm going to store in a variable called coin, whatever

6:42that value is, heads or tails.

6:43And now, just so I can see what's going on, let's go ahead

6:46and print out the value of that string coin

6:49All right, let me go ahead now and run this program in my terminal window.

6:52Python of generate.py, Enter.

6:55And it looks like the first coin toss was the heads.

6:58Let's go ahead and run it again.

7:00And it looks like it was heads again.

7:02Maybe you want to chime into the chat here.

7:03If I run it a third time, what's it going to be this time?

7:06If you want to type your thoughts in the chat,

7:10you might think there's a bug here.

7:11But this is probability in action.

7:14If I go ahead and hit Enter a third time there,

7:16it's actually now tails And again, tails and again tails and again tails

7:21and again tails and again heads.

7:23Now, if we did this an infinite number of times,

7:25it would indeed work out to be 50/50.

7:27If we only do it a few times, it might not work out as cleanly.

7:31But that's how probabilities indeed work.

7:33All right, so I've got that now working.

from

7:35Could I have implemented this in a different way?

7:37Well, let me show you an alternative to actually using the import keyword alone

7:42and let me introduce the keyword from in Python.

7:45So from is a keyword in Python that you can use when importing functions

7:50from a module, but it allows you to be a little more specific than import alone.

7:55So if I go back to my code here, it's worth

7:57noting that what technically I'm doing here by importing random

8:01is I'm technically importing everything that's in that module.

8:04So not just the function called random.choice but a few other functions

8:09as well.

8:10So instead of using this line of code at the top of my file,

8:12import random, which will technically give me access

8:15to all of the contents they're in, a downside of that

8:18is that I have to type in random.choice, random.this,

8:22random.that because all of the functions I'm calling

8:24have to be associated with the scope of that module.

8:28Well, suppose that I just want to call the function as its name, choice.

8:31I can do that as well.

8:32Let me replace this first line here with from random import choice.

8:37And what this does effectively is it loads the function's name choice

8:42into my current namespace into the scope of the file I'm working in.

8:47What that means is that I now no longer have to specify

8:50which choice function I mean.

8:52I can just say choice.

8:53And so it loads it into the local namespace

8:56that is into my local vocabulary, if you will, so I can just now say choice.

9:00This might be advantageous in what cases, do you think?

9:05When might you want to import the name of the function explicitly like this

9:10as opposed to just saying random.choice--

9:12random.choice throughout your code when calling a function?

9:16Any instincts here for this alternative import using from?

9:21AUDIENCE: Hello, I'm Mohammed Omar from Egypt.

9:23And maybe if we have a variable that its name is basically like choice

9:29if I have a variable called the choice.

9:30So I need to differentiate which trays I choose.

9:33So I'm going to choose random data choice.

9:36DAVID MALAN: Yeah, really good instincts.

9:38By using the first approach by just importing random,

9:40you're making sure that all of its contents

9:42are associated with or scoped to the random module

9:46so that you can have your own choice function.

9:49You can have your own choice variable.

9:51You can use the same names as all of the functions or variables that

9:54are stored inside of that file without them colliding, so to speak.

9:58And this is a good thing.

9:59In older languages, it was the case that if you imported someone's library,

10:03you better hope that you're not using the same functions

10:05or variables as they are because you might

10:08in fact have some kind of conflict.

10:09Python and certain other languages allow you

10:11to scope the names of those functions and variables to the file or the module

10:16that they come from.

10:16So that's a good thing.

10:17But honestly, this is such a short program.

10:20Or equivalently, maybe I'm using the choice function

10:23in so many places calling random.choice, random.choice, random.choice.

10:28It's just making my code longer and longer and longer.

10:31Marginally so, but hey, just getting ugly and annoying,

10:34I can simply import choice and now tighten up my code a little bit.

10:38So as with so many decisions in the past,

10:40there's not necessarily one right approach or another.

10:43It depends.

10:43But I think for those very reasons, sometimes

10:45it's better to do what we did the first time, which

10:48is only import the module so as to retain the scope therein.

10:52Well, let me propose that we transition to another function that

10:55comes with Python's random module.

10:57And that's this here from the documentation randint.

11:01It's a bit hard to say, but it implies get back a random int.

11:04And if you read the documentation, it's a random int that's between A and B

11:08inclusive.

11:09So if you were to pass in 1 for A and 10 for B,

11:12you would get back a number between 1 and 10 inclusive, including the 1

11:17and including the 10 potentially.

11:18Each with a 10% probability.

11:21So how might I go about using a program like this?

randint, shuffle

11:23Well, let me come back to my generate the py file.

11:26And why don't we go ahead and try generating

11:28a random number between 1 and 10?

11:29You might do this frequently in the real world.

11:31When you just want someone to pick a random number,

11:32you tell them as much in the human response.

11:34Let's get the computer to do the same here.

11:37Let me go ahead and delete my two lines of code at the bottom

11:39but keep my import random.

11:41And let's go ahead and define a variable this time called number,

11:44set it equal to the return value of random.randint

11:47and now passing A, a value of 1 and B, a value of 10.

11:52And now, let's go ahead and print the number.

11:55I'm going to go ahead in my terminal window

11:57and run Python of generate.py and hit Enter.

12:004.

12:01A Python of generate.py and hit Enter.

12:048, again, 9, again, 7, again, 10, again, 2, again.

12:11And we can do this all day long.

12:13And if we add all of those up, they should end up

12:15being with 10% probability each.

12:17Now, how might you use this information?

12:19Well, maybe we're playing a guessing game.

12:21Or maybe we're trying to randomize the behavior of some character in the game.

12:25You can imagine using very simple building blocks like this just

12:29spicing up your program by getting it to do things

12:32a little less predictably because you're choosing these values seemingly

12:36randomly.

12:36And you're deferring to Python to actually do

12:38the generation of these numbers using its own algorithms and its own math.

12:43Well, what more could we do here?

12:44Let me propose that we introduce another function that

12:46comes from this random library.

12:48Yet, another that you yourself don't have to implement, shuffle.

12:52If you read the documentation for shuffle in the same random module,

12:55you'll see that it takes in a list, for instance, of values

12:58and just shuffles them up.

13:00It randomize them like a deck of cards.

13:02Here, you might shuffle them so as to put them into seemingly random order.

13:06Well, how do I use this based on this function's name?

13:09Well, let me propose that we go back to VS Code here.

13:11And let me go ahead and this time do the following.

13:14Because I need to shuffle something like a deck of cards,

13:17let me go ahead and not just import random.

13:19But let me give myself a variable called cards that's going to be of type list.

13:23And just so I have something to shuffle, I

13:25don't need all 52 cards in a typical deck.

13:28I'm just going to shuffle three cards.

13:29A Jack, a Queen, and a King.

13:32I could call those strings anything I want,

13:34but I just wanted a list of some values so as to shuffle them up.

13:37That is randomize the order therein.

13:39Well, how does this now work?

13:40If you read the documentation for random.shuffle,

13:43you'll see that it shuffles the argument in place.

13:47That is unlike many of the functions we have seen.

13:49It doesn't return to you a value that contains

13:52the shuffled cards in this case.

13:54It actually shuffles the list it's given itself.

13:57So what this means for my code is that I need

13:59to do something like this-- random.shuffle

14:02and pass in the variable containing those cards.

14:06And then on a final line here, how might I go about printing the cards?

14:11Well, I could do this, and I could say print card.

14:14But if I do that, I'm actually going to see Python syntax for lists.

14:17And it's just going to format in its own way using commas and the like.

14:21I want to print these cards out one at a time

14:23just because I think it'll look a little better so we can use some of our syntax

14:26from loops and say something like this--

14:28for card in cards, go ahead and print out the current card.

14:33So what's now happening here?

14:35Line three, I'm defining a list of three cards in this order--

14:39Jack, Queen, King.

14:41I'm then shuffling those same cards on line four.

14:44And then on line five, I'm using a for loop

14:46for each of the cards in that list printed out one at a time

14:50and because I'm using print one line at a time.

14:53Well, let's see the results.

14:55Down here in my terminal window, I'm going

14:56to run Python of generate.py and hit Enter.

14:58Queen, King, Jack seemingly shuffled because that's not

15:02the order I defined earlier.

15:04Let's do it again.

15:05Queen, King, Jack.

15:07Hmm, OK, that happens to be the same.

15:09But let's see.

15:10This could just be bad chance.

15:11There we go.

15:12Jack, Queen, King.

15:14Doesn't look like it's shuffled, but at least

15:16we're getting back different orderings now.

15:18Again, Jack, Queen, King.

15:20Hmm, not so good.

15:21Jack, Queen, King.

15:23Not so good.

15:23This is someone you probably want to play against with cards.

15:26Queen, Jack, King, there we go.

15:27But of course, we only have three cards here.

15:30So there's not that many permutations we might see.

15:32And if we do this over time, we will see all of them.

15:35But if we had, of course, 13 or 52 cards,

15:37we'd see a lot more permutations instead.

15:40So we have now these three ways to generate random information.

15:43One, a simple coin toss if you want to start some kind of athletic event.

15:47One, pick a number between 1 and 10 if you

15:49want to decide something based on that.

15:50And now, using shuffle, we can even take in a list of things

15:54and shuffle them about so that we get some kind of random behavior.

15:58Well, let me pause here and see if where there's

16:00any questions yet on random, on modules, or any of these three functions.

16:06AUDIENCE: Yeah, can we increase or decrease

16:09the probability of cards if we want to?

16:14For example, there are three.

16:16There is a 33% chance of probable B. So is there

16:19any chance to increase or decrease the probability?

16:22DAVID MALAN: Can you set these probabilities

16:24not using these same functions?

16:26Can you set the probabilities?

16:28But you can absolutely implement some of your own functions

16:31or use more sophisticated functions that do exist in this library and others

16:34to exercise more control.

16:36These are meant to be very user-friendly and simple functions, certainly

16:39the ones we looked at, that give you equal probability for all of those.

16:42But absolutely you could skew things, though, hopefully,

16:44if you're implementing a gambling game or the like,

16:47you're not actually making some cards more probable than others.

16:50Allow me to turn back now to our implementation here of this randomness

16:55and consider how we might leverage other types of functionality that

16:58aren't necessarily in this specific library here.

statistics

17:01Well, it turns out that Python also comes with a statistics library.

17:04And this contains all sorts of functions for doing

17:06things more statistical in nature, namely calculating

17:10means or medians or modes or other aspects of a data set

17:14that you might want to analyze.

17:16So how might we use the statistics module in Python?

17:19Well, we might first just take a look at it's documentation

17:21like any other module in Python.

17:23And we'll see within that library that there's a whole bunch of function.

17:26And one of those functions is one that's quite simple.

17:28It's average.

17:29A function that allows you to calculate the average of some numbers

17:33that you've passed in.

17:34Let me go ahead and in VS Code in my terminal window, open up a new file

17:38called average.py.

17:39And at the top of this file, I'm going to import

17:41a different library this time, namely the statistics module in Python.

17:46And now, I'm going to go ahead and call a function that I know comes

17:49in that module, namely mean for the average of some values.

17:53And I'm going to call statistics.mean.

17:55And I'm going to pass into this function mean, a list of some values.

18:00And let's suppose that I'm quickly trying

18:01to calculate what my current grade average is in school.

18:04And I did really well on my first test.

18:06And I got 100%.

18:07And on my second, I did well but not as well.

18:10And I got a 90.

18:10And ironically, I'm not very good with math.

18:13So I'd like to figure out what my average now is between those two tests.

18:16So let me go ahead now and in this list, type in the number

18:19100, comma, 90, thereby passing in a list of two values, two INTs, 190.

18:25And outside of those are the parentheses because, of course,

18:28this is now the argument I'm passing to the function called mean.

18:31And this function mean is in the module called statistics.

18:35Well, it's not that interesting to just calculate the mean if I don't actually

18:38see what it is.

18:39So let me additionally pass the return value of that mean function

18:43to the print function as usual.

18:45Let me now in my terminal window in VS Code, type

18:47in Python of average.py and hit Enter.

18:50And voila, as you might expect, my average is 95%.

18:54So the difference here is that I'm just using a different module that

18:57still comes with Python.

18:58But I need to import it instead of, for instance, the random module instead.

19:02And this time, I know from the documentation

19:04that there exists a function called mean.

19:06Well, it turns out there's even more functionality that comes with Python

19:10and that comes with other modules in Python.

Command-line Arguments, sys

19:13And there's this feature generally known as command line arguments.

19:16This is a feature, not just of Python, but of languages

19:19more generally that allow you to provide input not when

19:22prompted inside of a program as happens whenever we call the Python function

19:27input.

19:28But rather, there's this feature, command line arguments of programs,

19:32that allows you to provide arguments that

19:34is input to the program of just when you're executing at the command line.

19:38So up until now, for instance, recall that we've generally

19:40run Python of something.py.

19:42For instance, Python of hello.py.

19:45And I've never once really executed any words or phrases

19:49after the name of the file, but I could.

19:52In fact, when you're running programs in a command-like environment like we are,

19:57you can provide any number of words or numbers or phrases after the command

20:02that you're typing.

20:03And all of those will somehow be passed in as inputs to the program itself.

20:08You don't have to prompt the user for one thing at a time

20:11by manually calling that input function.

20:14So what does this mean in real terms?

20:15Well, let me go ahead back into VS Code here.

20:18And let me propose that we consider how we might leverage a certain module.

20:23I'm going to go ahead and create a file called name.py.

20:27And I'd like to use a new module this time that's

20:30going to give me access to values that have been typed at the command line.

20:35But what's this module going to be?

20:37Well, this one's going to be called sys.

20:39And sys, short for system, contains a whole lot of functionality

20:42that's specific to the system itself and the commands that you and I are typing.

20:46The documentation for this module is at this URL here.

20:49And it lists all of the various functions and variables and the like

20:53that come with that module.

20:54But we're going to focus on something a little more specific,

20:57namely this thing here.

20:58It turns out in the sys module in Python,

21:01there is a variable that just magically exists for you called argv.

21:06It stands for argument vector which is a fancy way of describing

21:10the list of all of the words that the human typed in at their prompt

21:15before they hit Enter.

21:16All of those are seemingly magically provided to you via Python

21:21in a variable called sys.argv.

21:24This variable is a list, which means that the first element is going

21:27to be the first word that you type.

21:29The second element is going to be the second word

21:30that you typed in, so forth.

21:32And by way of this list, then, can you figure out

21:34what words did the human actually type at the prompt and maybe use that

21:38to influence the behavior of your own program?

21:41So what does this mean now in real terms?

21:43Well, in this new tab called name.py, let me go ahead and import sys.

21:47Within that sys module is going to give me access to sys.argv, but how might

21:52I want to use it?

21:53Well, let's do this.

21:54Instead of writing a Hello World program that all of these times

21:58has just looked for the return value of input

22:02to figure out what the user wants me to print,

22:04let's go ahead and just expect the user to tell us

22:06when they run the Python program itself, what their name is.

22:10And suppose this time, I'd like to generate a whole bunch of name tags,

22:13initially just one.

22:14And in the US here, it's very common to wear a sticker on your lapel that

22:17says Hello, my name is David.

22:19So I want to print out some text that resembles that.

22:21The idea being maybe I could enhance this program someday

22:24to even send that text straight to the printer

22:26and dynamically generate those name tags.

22:28Well, let me go ahead now and do this.

22:30Let me go ahead and print out as always, Hello.

22:32But I'll say a little something more this time

22:34to make things more interesting.

22:36Hello, my name "is," quote, unquote.

22:38And then after that, I normally have been

22:41in the habit of calling input, storing the return value in a variable,

22:45and passing in the name of that variable here.

22:48But I'm going to instead jump right to this--

22:50sys.argvbracket1.

22:53And that's it.

22:55I'm going to have a program here that says Hello, my name is followed

22:59by whatever is in sys.argvbracket1.

23:02And notice, this .argv again is a list.

23:04And recall from our discussion of loops and in turn list,

23:07we use this square bracket notation to get at the various elements

23:11inside of a list.

23:12All right, let me go down now into my terminal window

23:15and run Python of name.py.

23:17But this time, rather than just hit Enter

23:19and wait for the program to prompt me for my name,

23:21let me proactively just tell this program what my name is

23:24at the so-called command line.

23:26Here we go.

23:27D-A-V-I-D separated with a space from the name of the file so that now when I

23:31execute Python, name.py David, I see on the screen, voila, Hello,

23:37my name is David.

23:38So based on this demonstration alone, I think

23:41we can infer exactly what's going on in sys.argv

23:44even though it sounds certainly at first glance, rather complicated here.

23:48Let's look up.

23:49At sys.argv, I'm going to bracket1 here.

23:53So clearly, sys.argvbracket1 is storing D-A-V-I-D. But it's one.

24:01In the past when we looked at loops, recall

24:03that we said that they were zero index.

24:06That is the first element is zero.

24:07The next element is one.

24:09This next element is two and so forth.

24:12And yet, here I am treating it as though my name

24:14is at the start of the list one.

24:16Well, let me ask this question, what is probably in sys.argv of 0?

24:23What is probably in sys.argv of 0--

24:27the very first element actually in that list?

24:30AUDIENCE: Oh, yeah.

24:32I think it's like in C, the name of program.

24:37DAVID MALAN: Indeed, it's indeed like in C. Another language

24:40is the name of the program.

24:41Well, if we consider what it was I typed,

24:44I certainly typed Python because that's the name of my interpreter.

24:47And we don't really need to know that because we're using Python itself.

24:50But after that, I did type two things.

24:52I typed name.py as I've done so many times any time

24:55I want Python to the interpreter program I've written.

24:58And it turns out by convention, what Python

25:00does is it stores in sys.argv the name of the file that you're executing

25:05or interpreting followed by any number of other words that you type.

25:10So all this time, we could have been accessing

25:12the name of the program, which frankly, isn't all that interesting.

25:15But we can also now access words that are typed after that prompt as well.

25:20But of course, if I don't type anything in, what might happen here?

25:25This might be naive of me to assume that there's always

25:27going to be something at location1 in sys.argv.

25:30Let me go ahead and try this.

25:32Python, name.py.

25:33And I'm not giving you my name because at this point,

25:36I might not even know that you want my name to be typed.

25:39So let me hit Enter now.

25:40And uh, oh, we see now an error.

25:43A so-called exception in Python, this one's a new one.

25:46This one's an index error that elaborates list index out of range.

25:51And turns out this is actually one of the most common mistakes

25:53in programming, whether you're using a list in Python

25:56or arrays or vectors in other languages, is

25:59to try to access some element that does not exist.

26:02You try to go too far to the left.

26:03Or you try to go too far to the right in this object that

26:08is just a list of some values.

26:10So of course, the mistake here is that I'm

26:13assuming there's going to be something at location1

26:15when really, it's location0.

26:17That's the only one that has a value.

26:19But fixing this is not going to amount to doing bracket0

26:23because now if I go ahead and rerun this program with no other words

26:27after name.py, it says Hello, my name is name.py, which is fine

26:31if we're making a name tag for the program, but that's not,

26:33of course, what my goal here is instead.

26:36So if the fix is not just to change the one to a zero,

26:40how else might I handle this error?

26:43How else might I handle this error?

26:46This index error that happens if the user just doesn't remember to

26:49or doesn't know to type their actual name at the prompt.

26:53AUDIENCE: We could always put an exception into the program,

26:56say, if there's nothing at location1, we just come out

27:03and say, OK, we haven't got parameter or something.

27:06But if there is, we continue along with the program.

27:09DAVID MALAN: Perfect.

27:10So if I might simplify, we can try to execute this line of code,

27:13except if there's an error, we'll deal with it in some other way.

27:16Now, ideally-- and once I'm a strong enough programmer,

27:19I would have anticipated this and written the following code

27:22from the get go.

27:23But when you're learning, it's certainly reasonable to see an error.

27:25Oh, I didn't realize I should detect that and then

27:28go back and improve your code.

27:29But of course, if you read the documentation,

27:31you ingrain some of the lessons learned from the past.

27:33You'll get into the habit of trying and checking for some of these exceptions

27:37yourself.

27:38So let me solve this in one possible way as you've proposed here.

27:41Let's try to handle this exception as follows.

27:43Let me go ahead now.

27:44And instead of just blindly calling this print line,

27:47let me try to print out Hello, my name is such and such,

27:51except if there is an issue, specifically an index error, then

27:56what do I want to go ahead and do?

27:58I'm going to say something like too few arguments.

28:01I could be more explanatory than that.

28:03But for now, I'm just going to explain to the user

28:05that they gave me too few arguments, too few words at the prompt.

28:08So now, it's still not going to work in quite the way I want.

28:12I'm still not going to be able to generate their name tag.

28:14But at least, they're not going to see some cryptic error message

28:17and think that they themselves broke the program.

28:20Let me go ahead now and run Python of name.py Enter and too few arguments.

28:23OK, let me go ahead now and do Python of name.py and type in my name, David.

28:28And now we're back in business.

28:30And I see that my name is on the screen too.

28:33But strictly speaking, I don't have to try to do this.

28:37I could actually be a little more defensive in writing this code.

28:41And maybe I could check whether or not the user has indeed

28:44provided a name or multiple names at the prompt so as to give them

28:48more refined error messages as well.

28:51So how might I do this?

28:52Well, me go and undo the exception handling I've added.

28:56And why don't I instead more modestly try to do this?

28:59Let me go ahead and introduce a conditional here.

29:01If the length of sys.argv is less than 2 or equivalently equal to just one

29:09value--

29:10but I'll just stick with less than 2 for now,

29:12then go ahead and print out two few arguments.

29:17So I want ultimately two arguments.

29:19I want the name of the program at location0.

29:21And I want the name of the human at location1.

29:24So that's a total of two arguments.

29:26So if I have fewer than two arguments, let's

29:28tell the user with this print line, L if the length of sys.argv

29:32is say greater than 2, like they typed in too many words at the prompt, well,

29:36let's tell them, print, quote, unquote, "too" many arguments.

29:40Else if they did get it right, and they gave me exactly two arguments.

29:44Else, let's go ahead and print what I actually care about.

29:48All right, let me go down to my terminal window

29:50here and run Python of name.py and voila.

29:52Uh, oh, a completely different type of error.

29:55This one a syntax error, which we've seen in the past.

29:58Now, a syntax error recall is mea culpa, like, I messed up here.

30:01And I wrote invalid syntax.

30:03And so no amount of conditionals or exception handling's

30:07really going to catch this one.

30:08I need to go back and just get my program

30:09to work because it's not running at all.

30:11Well, let me go up here and see.

30:14Line four is the issue.

30:16And indeed, it looks like I have an unterminated string here.

30:19I need to go ahead and now add this double quote.

30:22So let me go ahead now.

30:23And with that red herring gone, let me rerun Python of name.py and hit Enter.

30:27And now, we see too few arguments.

30:29OK, maybe it wants my full name.

30:31Let me go ahead now and run Python of name.py, David Malan,

30:35typing in both words after the name of the file and hit Enter.

30:39And now, of course, it's too many arguments.

30:41Fine.

30:41Now, I'll oblige and do Python of name.py and just David.

30:44And there we have it.

30:46My name tag printed on the screen.

30:48So strictly speaking, we don't have to handle exceptions

30:51if we can be a little smarter about it and just check for the things

30:54that we're worried about, especially if we want

30:56to give the user more refined advice.

30:58We don't want to just tell them no, something went wrong

31:00or we don't want to pass.

31:01We want to tell them no, that's too few or no, that's too many.

31:05We have conditionals in our vocabulary already

31:08via which we can now express that.

31:11Well, let me pause here and see if there's any questions now

31:13on how we handled the error before with the index error

31:16or how now we're just proactively avoiding all index errors altogether

31:21by just checking first, is it too few?

31:24Is it too many?

31:25Or is it exactly what we want?

31:27AUDIENCE: Hi, yeah, thank you.

31:28So I was wondering, you touched upon using your full name.

31:36Is there a way going forwards that perhaps we

31:40have people that want their full names and want just their first name

31:44that we separate that into, oh, this person has full name.

31:47This person has just the one name?

31:50DAVID MALAN: Absolutely, and allow me to propose we come back

31:55to that support for multiple names.

31:57But indeed, we could do that.

31:59And I should note too, though, we can support

32:02full names right now if I do this.

32:04Instead of typing in David space Malan, which is problematic because again,

32:08by definition of how are argv works, each word

32:11ends up in a specific location in the list.

32:14But if I add quotes, single quotes or double quotes at the command line,

32:18now, Python will view this as two total things.

32:21The name of the file and this full name.

32:23And now, when I hit Enter, I don't see the quotes.

32:25The whole thing is passed in as my full name.

32:28And if I want to adapt this further for multiple people,

32:30we'll be able to do that as well.

32:32Other questions now on this version with if, elif, else, or on except before.

32:37AUDIENCE: Python.

32:39I want to ask you, can we use multiple else's statement?

32:43DAVID MALAN: Can you use multiple else's statements?

32:45No, else is the last catchall statement that you can have.

32:48You can have multiple elif statements in the middle but not multiple elses.

32:55AUDIENCE: [INAUDIBLE]

32:56DAVID MALAN: All right.

32:57All right, well, let's turn our attention back now to this code

sys.exit

33:00and see if we can't refine it a bit more by adding

33:02in some additional functionality that we get with modules like the sys module.

33:06One of the things I don't love about this version of the code

33:09even though arguably it is now correct is that the essence of my program,

33:14which is just to print out the name tag, is relegated to this else clause.

33:19And that's fine.

33:20Logically, it's correct, but generally speaking,

33:24there is something nice about keeping all of your error

33:26handling separate from the code that you really

33:30care about having all of these ifs, elifs, perhaps at the top of your code

33:34that are checking to make sure that all of the data's as expected.

33:37But then it would be nice if only for design sake

33:41not to hide in this else statement the actual code that you care about.

33:45I would prefer, for instance, to do something logically like this.

33:49I could check for errors up top.

33:51And then down here, print the name tag.

33:54It would be nice if those are distinct blocks of code all of which

33:58are here left aligned.

33:59But there's a problem with what I've just done here.

34:02Logically, what bug did I just introduce by getting rid of the else

34:08and introducing line 10 on its own with no indentation

34:12outside of the conditional?

34:14What bug have I just introduced?

34:16What mistake to be clear?

34:19AUDIENCE: Name error.

34:20DAVID MALAN: Ironically, it's a name error but not a name error exception.

34:25It's an error with my name, but I think you're frozen for me.

34:30It's going to raise an exception because even

34:32though I'm checking the length of sys.argv up top

34:36and even though I'm checking it again for being greater than 2, not just less

34:39than 2, but greater, I'm still then blindly and incorrectly assuming

34:44it's now going to exist.

34:45So just to be clear, if I run Python of name.py and I don't type any argument--

34:50I've got too few--

34:51I think I'm going to see that I have too few,

34:53but I'm also going to see that same exception.

34:56At the very top of my terminal window's output,

34:58there's my error message, too few arguments.

35:01But again, on line 10, I blindly proceed to still index into my list

35:05at location1 which does not exist.

35:08So it turns out there's a better way to handle errors like this, especially

35:11if you're writing a program in Python that's just meant

35:14to run briefly and then exit anyway.

35:17But maybe we could start to exit prematurely if the program itself just

35:22can't proceed.

35:23If the user has not given us the data we want,

35:25perhaps, we should just exit the program earlier than we might otherwise.

35:30So let me go ahead and do this.

35:31Let me go ahead and remove my comments so as to focus only on the code here.

35:35And let me propose that instead of just printing,

35:39quote, unquote, "too" few arguments, I'm going to use one other function that

35:43comes with the sys module.

35:44I'm going to go ahead and call sys.exit.

35:48And as the name suggests, it's going to do exactly that.

35:50With the system's help, it's going to exit my program then and there

35:55on line four.

35:56Why is that OK?

35:57Well, if you gave me too few arguments, I

35:59have nothing more to say to you, the user.

36:01I might as well exit a bit prematurely.

36:03And I can do this as well on line six.

36:05Let's go ahead and not just print that, but sys.exit, quote, unquote,

36:08"too" many arguments.

36:10Print out that message and just exit right there.

36:12Now, I can trust that by the time I get to line eight,

36:16every error condition has been checked for.

36:19And so it's safe for me to assume that there is in fact an item at location1

36:25in sys.argv.

36:26So let me go ahead now and run this, Python

36:29of name.py, Enter, too few arguments.

36:32But I'm back at my prompt.

36:34Nothing more has happened.

36:36Let me run it again.

36:37Python of name.py David Malan with no quotes, Enter.

36:41Too many arguments is now printed here.

36:42Finally, Python of name.py just David, Enter.

36:46Hello, my name is David.

36:48So we have then in sys two forms of functionality.

36:52Now, we have access to this variable, sys.argv, this argument vector,

36:55that gives me all of the words that were typed at the prompt,

36:58including the program's own file name.

37:00And it turns out if we read further in the documentation,

37:03there's an exit function that can take different types of input.

37:06But if I pass out a string like this, it will indeed print that string for me

37:10and then exit from my program then and there.

37:13Questions now on exiting from programs like this.

37:17To be clear, all of this time once Python gets to the bottom of your file,

37:22it's going to exit anyway.

37:23So I'm using sys.exit now just to make sure that I exit earlier than

37:28otherwise.

37:28AUDIENCE: My question is about the sys that arg--

37:32argv.

37:33So is that capable of accepting or taking multiple elements at once?

37:40Let's say, for example, Python name.py, David Malan.

37:45I'm a male, 20 years old.

37:48And if let's say I only want to access your name, which is at the first index.

37:53And then your age is, say, at the sixth index.

37:59Can I say sys.argv1 and another one for six to access what I just want?

38:07Is that both for sys.argv?

38:10DAVID MALAN: Short answer-- yes, I think if I understand your question

38:13correctly, whereby, you're proposing to have

38:15many words at the end of the command.

38:17And you want to access those individual words.

38:19Absolutely.

38:20At some point, it gets a little fragile, I would say,

38:24if you're typing so many words at the prompt that the order really matters.

38:28And so it turns out there's a lot of programs.

38:30And there's functionality in Python that can

38:32allow you to provide those values, like name or age

38:36or any number of other fields in any order

38:39you want, but a pass in a bit more information textually

38:43that tells the program how you want to use it.

38:45So in short, what you're describing is possible.

38:47And let me do a small incarnation of it as follows.

38:51Let me propose that we go back to my code here.

38:54And let's propose that we actually now want

38:56to support multiple values at the prompt.

38:58So there's going to be no such thing as too many arguments.

39:01Suppose that I want to generate name tags not just for David, but for David,

39:05for Carter, for Rongshin, for others in the group who

39:08all want their name tags as well.

39:10So I'm going to go ahead and do this.

39:11I'm going to get rid of my elif condition

39:13because I don't want to limit the maximum number of words

39:16that are typed at the prompt anymore.

39:17I instead want to iterate over every name at the prompt.

39:23So I'm going to say this.

39:24For arginsys.argv, go ahead and print out this time, arg.

39:32So what am I doing here?

39:33Well, even though the syntax is a little different,

39:36the idea's the same as before when we've had loop.

39:38I'm using a for loop to iterate over a list.

39:42The list in question here is sys.argv.

39:45Arg is a variable that I'm creating on the fly.

39:48The for loop is going to make sure that the first time through this loop, arg

39:51is set to the first word on the command line.

39:53The second time through the loop, Python's

39:55going to make sure that arg is now set to the second thing on the command line

39:58and so forth.

39:58That's just how a for loop works.

40:00It updates the variable for us.

40:02I don't have to call it arg.

40:03I could call it name so long as I change it to name in both places.

40:07But arg is reasonable if I'm iterating over arguments more generally.

40:10If I now run this program, though, unfortunately, there's

40:14a little bit of a bug.

40:16Even if I type in David and Carter and Rongshin,

40:20I'm not going to get just three name tags.

40:25In your mind, does anyone see the bug I'm about to trip over?

40:29It's not a huge deal if I've got enough name tags to go around.

40:34But I'm going to be wasting one because this

40:36is going to print not three, but four name tags, whereby, the first contains

40:40the name of the program itself.

40:42Maybe not a big deal.

40:43Maybe that's the sticker we don't bother handing out, but it's wasteful.

40:46And it does look wrong.

40:47So how could we get access to not all four elements of argv

40:52but just a slice of argv?

40:54And this is actually a technical term in Python and some other languages.

Slices

40:58To take a slice of a list means to take a subset of it

41:01maybe from the beginning, maybe the middle, maybe the end.

41:04But a slice is a subset of a data structure like a list.

41:08Well, how do I actually do this in code?

41:10Well, in Python, it's actually very easy to take a slice

41:14of a list that is a subset thereof.

41:16You can simply do this.

41:17At the end of the list name, sys.argv in this case, you can use square brackets.

41:22And then in those square brackets, you can

41:24specify the start and the end of the list that you want to retain.

41:29I want to start at element1, not zero.

41:32I want to start at element1, and I want to just go to the end.

41:36So I'm actually going to omit a second number altogether.

41:38It's not necessary to have a second number.

41:40But I do need that colon because this is going to give me a slice of the list.

41:44It's going to give me a slice of the list that

41:46starts at location1, not zero.

41:48And the colon and then a blank just means

41:51it's going to give me everything else.

41:52So this is in equivalently going to slice off the first element of the list

41:56and give me a new list that contains just those three human names, not

42:00the name of the file itself.

42:02Let me try running this again.

42:03I'm going to run Python of name.py, David Carter Rongshin.

42:07This time hopefully, I'm going to get three and only three name tags,

42:11hitting Enter.

42:12And indeed, I've done now just this.

42:15So again, using some relatively simple syntax in Python,

42:18we can use square brackets not just to go to specific elements like bracket0

42:22or bracket1.

42:23We can also get subsets of the list, slices of the list

42:26by doing bracket something colon something where each of those

42:30some things is a number, the beginning or the end,

42:32and they're optional depending on whether you

42:34want all of them or just some.

42:37Any questions now on this version, which adds the loop and these slices

42:42with that new syntax?

42:45AUDIENCE: Can we slice starting from the end of the argument-- argument vector?

42:50DAVID MALAN: You can.

42:51You can slice something from the end of the argument vector.

42:54And this might blow one's mind a little bit.

42:57Let me go ahead and do this.

43:00Let's see.

43:00Let me go ahead and do negative one at the end.

43:03Using a negative number here and running the same command,

43:06we've just uninvited Rongshin from receiving a name tag here.

43:10So if you use a negative number, it has the effect

43:12of counting in the other direction from the end of the list.

43:17A good question there.

43:18Other questions now on slices, on looping over sys.argv?

43:23AUDIENCE: Hi, so I remember very early on when

43:26we were talking about only having two decimal places in float value.

43:34Is that in the same vein, like, because we use the code on 0.2F?

43:42Is that the same thing then?

43:44Why would the F be included then in the 0.2F as opposed to here when you just

43:50have the numbers?

43:51DAVID MALAN: A really good question.

43:53And it's just the short answer's that context matters.

43:56So there's only so many keys on our keyboard.

43:59And so we sometimes use the same symbols for different things.

44:02So what you're alluding to is the format code

44:05in an F string for actually formatting a number using a colon, using a period,

44:10using a number, using the letter F and so forth.

44:13And that is very specific to the F string feature of Python.

44:16This case has nothing to do with any of that syntax per se.

44:20This is just using a colon in a different context

44:22to solve this problem to implement a slice.

44:25The authors of Python could have chosen another symbol.

44:28But honestly looking down at my keyboard here,

44:29we don't have that many to choose from that are easy to type.

44:32So sometimes they have different meanings.

44:34A good question as well.

44:36Allow me to propose now, that we take things further

44:39and move away from using only those modules, those libraries that Python

Packages, PyPI, pip

44:43comes with to talk about more generally packages that exist.

44:47One of the reasons that Python is so popular and powerful these days

44:51is that there's a lot of third-party libraries

44:54out there as well, otherwise known as packages.

44:56Strictly speaking, Python itself has a term of art

45:01called a package, which is a module essentially

45:04that's implemented in a folder, not just a file but a folder.

45:08But more generally, a package is a third-party library that you,

45:12that I can install on our own Mac or PC or our cloud server

45:16and gain access to even more functionality

45:19that other people have implemented for us.

45:21Now, one of the locations you can get all of these packages

45:24is called the PYTI website, the Python Package Index which lives at this URL

45:30here.

45:31And this is a website that is searchable via the command line,

45:34as well as via the web, that allows you to download and install

45:37all sorts of packages.

45:39Even CS50 has some of its own packages in services like these.

45:43Now, there's a fun one out there that's a throwback to a command that's

45:46been around for years in command line environments called cowsay.

45:49Cowsay is a package in Python that allows you to have a cow say something

45:55on your screen.

45:56If curious to read up on it, its own documentation

45:58is on pi.py.org specifically at this URL here.

46:02But how do you actually get the package into your system?

46:06Well, technically, you could figure out how to download the file

46:09and maybe unzip it and put it into the right location on your Mac or PC.

46:13But nowadays, a lot of languages, Python among them,

46:15has what's called its own package manager.

46:18This one here called pip which is just one.

46:20So pip is a program that generally comes with Python itself, nowadays,

46:25that allows you to install packages onto your own Macs or PCs

46:29or cloud environment by just running a command.

46:32And then voila, you have access to a whole new library in Python

46:36that didn't come with Python itself.

46:38But now it's available on your system for you.

46:41Let's go back to VS Code here.

46:43And in my terminal window, I'm going to go ahead and type pip install cowsay.

46:48Now, what's going on here?

46:49Pip is the command, the package manager.

46:51And I want to install what package?

46:53The package called cowsay.

46:55I'm going to go ahead and hit Enter here.

46:56And after a little bit of output, it has successfully installed cowsay.

47:00Now, what does that mean?

47:01That means I can now go about importing this into my own code.

47:05Well, let's go ahead and see what this means.

47:07So let me go ahead and create a new file with code called say.py

cowsay

47:11because I want something to be said on the screen.

47:13And in my new tab here, I'm going to go ahead and import cowsay,

47:17which presumably is now installed.

47:19I'm now going to import sys as well because I'd

47:22like to use some command line arguments in this program

47:25just so that I can run it quickly.

47:26And without using the input function, I can get the user's name

47:30immediately from the prompt.

47:31And let me go ahead and do this.

47:33I'm going to do a bit of error checking proactively this time.

47:35And rather than use less than or greater than, I'm

47:37this time going to say if the length of sys.argv does equal 2.

47:43So if the human is provided just the name

47:45of the program and their own first name, we're good to go.

47:49I'm going to do the following.

47:51I'm going to call a function called COW in the package called cowsay.

47:56And I'm going to pass in a string, hello, comma.

48:00And then as in the past, I'm going to pass in just one string

48:03because according to its documentation, it's not like print.

48:06I can't pass in comma this, comma that.

48:08I can only pass in one string.

48:09So I'm going to concatenate it the contents of sys.argv, bracket1.

48:14So long as then I type in my name David after the name of this program,

48:20it should end up in sys.argv1 in which case, this line five of code

48:24should concatenate hello with my name with a space in between.

48:28And apparently, a cow is going to say it.

48:30So let's see what happens here.

48:32Let me go ahead and clear my screen and increase

48:35the size of my terminal window.

48:36Let me go ahead and run Python of say.py and type my name David and Enter.

48:42There is the program called cowsay.

48:44It literally has a cow say something on the screen.

48:47And this is a throwback to a program from yesteryear

48:50that tended to come with a lot of systems.

48:53This is otherwise known as ASCII art.

48:55It's a textual way using just keys on your keyboard

48:57to print pictures of sorts on the screen.

49:00Now, we can really go down the rabbit hole here.

49:02And there's questionable academic value of doing so.

49:05So I'll do so just once.

49:06Turns out the cowsay package comes with other functions as well.

49:10One of those functions, for instance, is T-Rex.

49:13And if I now increase the size of my terminal window,

49:16we'll perhaps see where we're going with this.

49:17Let me now run again, Python of say.py.

49:20This time, let me not provide my name just to see if it's broken.

49:23It's still OK because we have that if condition

49:26if the length of sys.argv equals equals 2 and only if it equals equals 2,

49:31do we do anything.

49:32That's why we're not seeing anything here.

49:34Let me go ahead and cooperate now, say.py space David.

49:38And it's no longer a cow.

49:40But if I zoom out on my screen, a T-Rex.

49:44Why?

49:45Just because these are the things you can do once you know how to program.

49:48You can even package them up and make them freely available to others

49:51as open source software.

49:52For us, it's demonstrative of a feature more generally here

49:56namely being able to install these third-party packages and how

49:59you might do so in Python.

50:01Now, I'll leave this up on the screen for a moment

50:03and see if there's any questions about cows

50:06or Tyrannosaurus rex's or packages more generally.

50:11I'm really qualified to speak to just one of those.

50:14AUDIENCE: Hi, I've got two questions it's a bit earlier than what's

50:19supposed to be.

50:20So the first question is the packages that you're

50:25calling to use in the program, are they the same

50:32as, let's say, something Java the same as calling a class, a Java file

50:42in order to use its functions?

50:45And my second question is, what's the actual purpose of using command line

50:52arguments as you used because is not really the best way to, as you say,

51:00be user friendly where as in let's say the person who's

51:06using the program doesn't know what they want--

51:10what the program's asking them?

51:12DAVID MALAN: Really good question.

51:13The first question about the comparison with Java, Python packages

51:17are similar to Java packages where you have something.something.something

51:20at the top of your program that gives you

51:22access to a class or something else.

51:24Python itself supports classes.

51:26More on those down the road.

51:27And you can do very similar things in Python as you can do with Java.

51:32But the analog really is Python packages to Java packages here.

51:36As for command line arguments, you ask a good question.

51:39Why do we use them, especially if they are literally user friendly?

51:42They're a little less user friendly to people

51:45who aren't in this Zoom to be honest.

51:47You and I as we learn more and more about programming

51:50and more about command line arguments, I daresay

51:52we'll become more comfortable with and tend

51:54to prefer the ability to customize commands using these command line

51:58arguments.

51:59Why?

51:59Productivity.

52:00It tends to make you faster because you get

52:02into the habit of knowing exactly how you

52:03can configure your software without having to manually answer questions.

52:07And case in point.

52:08All of this time have we been running Python of something.py.

52:13You could imagine not doing that.

52:15You can imagine typing only Python, hitting Enter.

52:18And then you're prompted for the name of the file you want to run.

52:20So you type in something.py, and then it runs.

52:23Not a big deal, but I would argue that over time, you're

52:26going to get a little tired of that TDM.

52:28And you would much prefer to just automate

52:29the command again and again and again, especially with little conveniences

52:33like being able to hit up and down in your keyboard history

52:36so as to rerun those same command.

52:38Automation is big too if you emerge from a class like this

52:41and start using Python to automate processes

52:44at work or for personal projects or the like,

52:46the ability to specify all of your inputs on the one line

52:49just means you can get work done more quickly.

52:51So hands down, absolutely.

52:53Using command line arguments is a more arcane feature of systems

52:58that most of us are no longer as familiar with because

53:01of Windows and Mac OS and other operating systems that

53:03have buttons and GUIs and menus.

53:05But the more comfortable you get with programming,

53:08I daresay the more you will tend to prefer these capabilities because they

53:12allow you to do things more quickly.

53:15With that said, allow me to propose that we take a turn toward, yet,

53:19another package that's particularly popular and just as easy

53:23to install all toward an end of using APIs.

APIs, requests, JSON

53:27Now, APIs are not something that's Python-specific.

53:29More generally, an API is an application programming interface.

53:33And it can refer to Python files and functions.

53:37But often, APIs really refer to third-party services

53:41that you and I can write code that talk to.

53:44Many APIs, but not all, live on the internet these days

53:47so that so long as you have a browser or so long

53:50as you have some experience with Python programming or programming

53:53in any language, you can write code that in effect pretends to be a browser,

53:58connects to that third-party API on a server,

54:01and download some data that you can then incorporate into your own program.

54:05Now, how do you do this?

54:07Well, Python has a very popular package that you

54:10can install via pip called requests.

54:12The requests library allows you to make web request,

54:16internet request using Python code essentially

54:20as though you were a browser yourself.

54:22You can automate, therefore, the retrieval of URLs

54:25that start with HTTP or HTTPS.

54:28The documentation for this library is that a URL like this,

54:31but it too can be installed at the command line.

54:33And even though it's third party, it's one

54:35of the most popular and commonly used packages out there in Python.

54:38And this too is one of the reasons again that Python is so popular.

54:42There's just so many solutions to problems

54:44that you and I have or are invariably going to have

54:47when we write projects of our own.

54:49There's just a really vibrant ecosystem, a really vibrant community

54:53of open source software that's that easy for us to install.

54:57Let me go back to my terminal window now and run

54:59pip install requests in order to install this package on my own system.

55:03And after some lines of output, I'll see that it's successfully installed.

55:06Now, let's go ahead and create a new file here.

55:09For instance, itunes.py.

55:11It turns out that Apple has its own API for their iTunes service.

55:15The software that provides you with the ability

55:17to download and search for music and songs and other information as well.

55:20And it turns out that-- let me go back over to my computer

55:23here and open up a browser like Chrome.

55:25And let me go ahead and visit this URL here,

55:27https://itunes.apple.com/ search?entity=song&limit=1&term=weezer.

55:32Search?entity=song& limit=1&term=weezer.

55:39Now, I constructed this URL manually by reading

55:42the documentation for Apple's API--

55:44application programming interface for iTune.

55:47And what they told me is that if I want to search for information about songs

55:51in their database, I should specify entity

55:54equals song so that songs and not albums or artists or something like that.

55:58If I just want to get back information on one song,

56:00I'm going to provide limit equals 1.

56:02And if the band I want to search for, the artist is Weezer,

56:05I should specify term equals Weezer.

56:07So with this, if I go ahead and hit Enter and visit this URL,

56:11I actually end up with a text file in my Downloads folder on my Mac.

56:15If I go ahead and open that text file that my browser just downloaded,

56:18we'll see all of this text here, which at first glance

56:20might look a bit cryptic, but it actually follows a pattern.

56:23Notice this curly brace at the start and notice this

56:26closed curly brace at the end.

56:28Notice this open square bracket here and notice this closed square bracket here.

56:32And in between those pieces of syntax are

56:35a whole bunch of strings and values.

56:37In fact, a whole bunch of key value pairs.

56:40What we're looking at here is a standard text format known as JSON--

56:43JavaScript Object Notation, which yes, is technically related to yet,

56:47another programming language called JavaScript.

56:49But JSON itself is typically used nowadays

56:52as a language agnostic format for exchanging data between computers.

56:57By language agnostic, I mean you don't have to use JavaScript.

57:00You can use Python or any other language to read JSON or write it as well.

57:05And it's a completely text-based format, which

57:07means that if I visit that URL with my browser, what gets downloaded

57:11is just a bunch of text.

57:12But that text is formatted in a standard way using curly braces

57:16and square bracket using quotes and some colons that ultimately contains

57:21all of the information in Apple's database on Weezer's song, at least,

57:25the first one because I limited it to one in their database.

57:29And that's an API, an application programming interface.

57:32A mechanism whereby I can access data on someone else's server

57:35and somehow integrate it into my own program.

57:39Now, of course, my browser, Chrome, is not something I wrote.

57:42I should actually write some Python code that perhaps pretends

57:45to be a browser to grab this same data.

57:47So let's do that.

57:48Let me go back to VS Code here.

57:50And let me write a program with code, itunes.py.

57:53And we're going to write some code via which I can then use the iTunes API

57:59and in turn, Python to get information about any band that I might want.

58:03I'm going to go here and import first the requests

58:06library, which I installed earlier in order to make those HTTP requests.

58:11I'm going to go ahead and import the sys library via which I'll have the ability

58:15to use command line arguments like specification of the band

58:18that I want to search for if not Weezer.

58:20And then down here, I'm going to go ahead and insert some error checking

58:24to say if the length of sys.argv does not equal to--

58:30so if the user does not provide me with the name of the file

58:33they want to run and the name of a band, and that's it, you know what.

58:36Let's just go ahead and exit for now.

58:39I could provide a more explanatory message.

58:41But for now, I'm going to keep things simple

58:43and just exit the program prematurely so that I can trust hereafter

58:46that sys.argv has what I want.

58:49And now, I have the opportunity to use the requests library to write

58:54some Python code that effectively is pretending

58:56to be a web browser so as to connect to that same HTTPS

59:00URL on Apple's own server.

59:03So now that I've guaranteed that the user has typed in

59:06not just the name of the file, but also the name of a band at the prompt

59:10giving me a length of two for sys.argv, let's go ahead

59:13and execute request stockget, which is a function inside of the request package

59:18that will literally get some response from a server.

59:21And the URL that I want to get is the exactly the same as before.

59:24https://itunes.apple.com/ search?entity=song& limit=1&

59:33term=previouslyweezer.

59:36But let's make this program a little interactive

59:39and actually allow the human to specify at the command line what

59:42artists they'd like to search for.

59:44So I'm going to go ahead and close my quote early and just

59:47append using the concatenation operator as in the past, sys.argv bracket1.

59:54And now, it actually be nice to store the response

59:57from the server in a variable.

59:59So I'm going to go ahead and say response equals

1:00:01and to store all of the response that comes back

1:00:04from the server in a variable called response.

1:00:06Down here now, I'd like to just understand

1:00:08what the server's returning to me to make sure I know how next to proceed.

1:00:12So this isn't going to be very pretty yet.

1:00:14But I'm going to go and print out response.json,

1:00:17which ensures that the data I'm getting back is formatted on my screen

1:00:21as exactly that, JSON, the same text format as we saw on my screen.

1:00:25It's not a useful program yet.

1:00:27I'm really just learning along the way.

1:00:29But let me go ahead now and increase the size of my terminal window

1:00:32and run Python of itunes.py and type in the name of a band like Weezer

1:00:37and hit Enter.

1:00:39And what we see on the screen formatted almost the same

1:00:42as before is exactly that same text.

1:00:44But what you'll see here is that this has been standardized now

1:00:48as a Python dictionary.

1:00:50What indeed Apple's returning is technically a JSON response,

1:00:54JavaScript Object Notation.

1:00:55But Python, the request library is converting it

1:00:59to a Python dictionary which happens to use wonderfully coincidentally, almost

1:01:04the same syntax.

1:01:05It uses curly braces to represent the dictionary here

1:01:08and a close curly brace to represent the end of it here.

1:01:10For any lists therein, it uses a square bracket here

1:01:14and a closed square bracket down here.

1:01:16It uses quotes-- single quotes in this case or equivalently double quotes

1:01:20to represent the keys in that dictionary.

1:01:23And after a colon, it stores the value of that key.

1:01:27And so you'll see that indeed we have a result count key whose value is 1,

1:01:31but then a more interesting Result key called results whose

1:01:35value is this entire list of data.

1:01:38Now, honestly, this is such a big blob of text

1:01:41that it's going to take me forever to wrap my mind around what I'm seeing.

1:01:44So let me propose temporarily we use another library in Python that

1:01:48will allow me to format my data a little more cleanly.

1:01:52It turns out that Python also comes with a special library called

1:01:56JSON that allows you to manipulate JSON data

1:01:59and even just printy print it that is formatted in a way that's going to be

1:02:02way easier for you and I to understand.

1:02:04So let me go back to my code here.

1:02:07Let me shrink my terminal window.

1:02:09And let me propose that just temporarily again we do this.

1:02:13Let me import this additional library, JSON, which comes with Python.

1:02:16So I don't need to install it manually with pip.

1:02:19And let me go ahead now and not just print out

1:02:21response.json which was that big blob of hard-to-understand text.

1:02:26Let me go ahead and use one other function here called json.dumps

1:02:31for dump string and pass to that function that response.json return

1:02:36value.

1:02:37So again, I'm just introducing another function

1:02:39who I claim has a purpose in life of pretty printing,

1:02:43nicely formatting on the screen the exact same information.

1:02:46And I know this from the documentation having done this before.

1:02:49But I'd like things to be nicely indented.

1:02:51And according to the documentation, if I pass in a named parameter of indent

1:02:56equals 2, that's going to indent everything at least two spaces.

1:02:59I could do four or something else.

1:03:01But it's going to be enough to help me wrap my mind around what

1:03:04the data is I'm getting back.

1:03:05Because again, I'm just learning along with you.

1:03:08So let me increase the size of my terminal window again.

1:03:10Let me run Python of itunes.py.

1:03:12And again, let's search for Weezer and hit Enter.

1:03:15And now, notice it's still a little bit cryptic

1:03:18because there's a lot going on here.

1:03:20But my gosh, I can totally read this more easily now.

1:03:24Notice now that I still see the first curly brace, which means hey,

1:03:27this is a dictionary in Python.

1:03:29A collection of keys and values.

1:03:31The first key is called result count.

1:03:33It happens to be displayed in double quotes now.

1:03:35But that's just an issue of formatting.

1:03:37It could be double or single so long as we're consistent.

1:03:39The value of that key is one.

1:03:42Why?

1:03:42Well, I told the URL to only limit the responses to one Weezer song

1:03:46so I've gotten a result set of one.

1:03:48If I increase that limit, I could probably get more.

1:03:51Then the interesting part of this response is really the data itself.

1:03:55Notice in the results key here, there's a really big value.

1:03:59The value is a Python list as implied by this square bracket.

1:04:05What does this list contain?

1:04:07Well, I know from skimming it earlier that this contains one dictionary.

1:04:11And that's why we see another curly brace here.

1:04:15So again, if this gets a little more complicated,

1:04:18keep in mind that a dictionary is just a collection of key value pairs.

1:04:22And Python uses curly braces to indicate as much.

1:04:25It is perfectly reasonable for a dictionary

1:04:28to be inside of another dictionary if the value of some key itself

1:04:33is another dictionary.

1:04:35So this is a common paradigm.

1:04:36And even though it might seem a bit cryptic,

1:04:38it's just something that allows us to associate more keys with more value.

1:04:42Now, most of this information, I probably don't care about.

1:04:45For instance, according to Apple, the unique identifier for Weezer

1:04:48is apparently 115,234.

1:04:52That might be useful if I'm making my own database

1:04:54and I want this to be searchable.

1:04:56But for today's purposes, all I care about is the name of the track,

1:05:00otherwise called track name as key.

1:05:02And the first song and only song because we limited it to one

1:05:05that we got back from iTunes here is the song

1:05:08that you might know by Weezer called Say It Ain't So.

1:05:12So now, I have a bit of a clue if my goal here is to implement a program

1:05:17called itunes.py that doesn't just dump the response from the server,

1:05:21which is admittedly very cryptic--

1:05:22but to print out all of the songs that iTunes has for the band called Weezer,

1:05:28maybe I can iterate over this somehow.

1:05:30So let me backtrack.

1:05:31Here's the key call track name.

1:05:34It is inside of a dictionary that is the value of results here.

1:05:39So how can I go about getting this?

1:05:42Well, let me go ahead and try this.

1:05:44Let me go ahead and shrink my terminal window back down

1:05:47and let me propose now for one final flourish.

1:05:49We don't just lazily print out the contents

1:05:52of that response because that's not interesting or pretty for anyone.

1:05:55Let's do this.

1:05:56Let me go ahead and create a new variable

1:05:58just for the sake of discussion called O for object.

1:06:01And I'm going to go ahead and call o equals response.json just

1:06:06to store that JSON response specifically in a variable called o,

1:06:11but I could name it anything I want.

1:06:13And now, I'm going to do this.

1:06:14For each result in that object's key called results,

1:06:21go ahead and print out that result's track name.

1:06:26And notice I have used exactly the same capitalization.

1:06:29Track name has a capital N. Result is all lowercase.

1:06:32And let me rewind before we run the actual program.

1:06:35In line eight, we are making an HTTP request

1:06:38using Python to the server just like you and I as humans type URLs

1:06:41into a browser and hit Enter.

1:06:43This is the Python equivalent thereof.

1:06:45I am then on line 10 just grabbing from that variable that

1:06:49contains the server's response, the JSON object that I care about.

1:06:53The thing between those curly braces at the very top and the bottom.

1:06:57But because we've poked around and because I

1:07:00read the documentation earlier, I know that that object

1:07:03has a key called results.

1:07:06And that results key again is a list.

1:07:08Now, at the moment, that list contains only one song,

1:07:11Say It Ain't So, because I limited my response to one.

1:07:14But even so, my loop will work.

1:07:16It's just going to iterate once.

1:07:17And each time through that loop, it's going

1:07:19to print the current result's track name.

1:07:22If I want to make this even more interesting,

1:07:24let me change this limit now from 1 to 50

1:07:26so I'll at least get back 50 track names instead.

1:07:29Let me go ahead now and increase the size of my terminal once more

1:07:33and go ahead now and run Python of itunes.py searching again

1:07:36for a band like Weezer.

1:07:38And here we go.

1:07:40And voila, there are 50 songs that iTunes has for Weezer.

1:07:44And if we scroll back up to the top here,

1:07:47we'll see that the very first one there is, indeed, Say It Ain't So.

1:07:51But now, we got Undone--

1:07:52The Sweater Song, Buddy Holly.

1:07:54Apparently another rendition of Say It Ain't So perhaps

1:07:56from another album, another Buddy Holly undone, my name is Jonas, and so forth.

1:08:01Questions now on this program which integrates Python with a real world

1:08:06third party API?

1:08:10AUDIENCE: Yeah, hi.

1:08:11Can we use break instead of system.exit?

1:08:15DAVID MALAN: Good question, but no.

1:08:16Break again is used to break out of things like loops like we saw earlier.

1:08:21Sys.exit is used to break out of the whole program itself.

1:08:25Use break for loops for now and use sys.exit to terminate

1:08:28the whole program.

1:08:29Good question.

1:08:30Other questions now on this program are others?

1:08:32AUDIENCE: From where we bring the name of the key results?

1:08:36DAVID MALAN: From where do we get the name of the key?

1:08:38AUDIENCE: Results itself.

1:08:40Yeah, and can we change the results, the name?

1:08:42DAVID MALAN: You cannot.

1:08:43So we could in our program.

1:08:45So the keys that come back in that JSON response, to be clear,

1:08:48come from iTunes.Apple.com.

1:08:51Some team of engineers decided for us what all of those keys would be called,

1:08:55including track name, results, result count, and everything else.

1:08:59You and I can absolutely store those same values in variables

1:09:03just like I'm doing here with O, just like I'm doing here with result.

1:09:06You can rename those keys anything you want using Python variables.

1:09:10But the JSON response is coming from that third party server.

1:09:14Other questions.

1:09:15AUDIENCE: Yes, sir.

1:09:16So I have a question related to cowsay package.

1:09:21So like, yes.

1:09:23So sir, what sort of ASCII graphics is it capable of putting?

1:09:29DAVID MALAN: The cowsay package.

1:09:31I would refer you to the URL in the slides

1:09:33earlier if only because it's more thorough.

1:09:36They have not just cows, but Tyrannosaurus rex's

1:09:38and several other animals as well.

1:09:40I should emphasize that this is not a package I suspect

1:09:42you will use much in the real world.

1:09:44It's really just meant to be representative of the types of packages

1:09:47you can install.

1:09:48But allow me to refer to the documentation for what more is there.

1:09:51But ASCII art is all we had before there were emojis, let alone GIFs and JPEGs

1:09:57and pings.

1:09:57But it's what's is immortalized in cowsay.

1:10:00Well, allow me to transition us back now to one final capability of Python which

Custom Libraries

1:10:06is that you yourselves have the ability to make your own libraries.

1:10:10Up until now, we've been writing all of our functions in our one

1:10:14file, Hello py and everything since.

1:10:17And now that we've introduced modules in Python, random and statistics,

1:10:22we can import those that come with Python.

1:10:25But that's other people's code as well.

1:10:26And we've now used pip, this package manager to install

1:10:29third-party packages as well in the system

1:10:31and using other people's code still.

1:10:33But to come full circle, what if you yourself

1:10:36find yourself implementing the same kinds of functions again and again,

1:10:40or you find yourself opening up old programs,

1:10:42copying and pasting code you wrote into new programs

1:10:45because you have the same problem yet again?

1:10:47A good practice would be to somehow bundle up that code you keep reusing

1:10:53and make your own Python module or package.

1:10:56You can keep it local on your own Mac or PC or cloud server.

1:10:59Or you can go through the steps of actually bundling it up, making

1:11:02it free and open source, and putting it on something like py, pi for others

1:11:06to use as well?

1:11:07OK, I'm going to go ahead and run code of sayings.py

1:11:10to create a brand new file called sayings.py which

1:11:13is going to be my own sayings module.

1:11:15I'm going to define a couple of simple functions in there.

1:11:18I'm going to define a Hello function that's going

1:11:20to take a name parameter as input.

1:11:22And that function is simply going to print out

1:11:25an F string that contains hello, comma, and then in curly braces,

1:11:28whatever that person's name actually is.

1:11:31Then I'm going to go ahead and define one other function,

1:11:33a goodbye function, that has def, goodbye, also

1:11:37takes a name as its input.

1:11:39And then that prints out by contrast and F

1:11:41string that says goodbye, comma, and then in curly braces, name.

1:11:45And now, just for good measure just so I can be sure

1:11:48that these functions are working as expected,

1:11:50I'm going to go ahead and define a main function in here

1:11:53too just for the purposes of testing.

1:11:55And I'm going to go ahead and define a main function that

1:11:57simply does a couple of tests.

1:11:59For instance, it calls Hello of, quote, unquote, "world" shall we say?

1:12:05And then it's going to call good bye of, quote, unquote, "world" as well.

1:12:09And hopefully what I'll see on the screen then

1:12:11is Hello world and Goodbye world when I run this program.

1:12:13Of course, as always, I need to explicitly tell

1:12:16Python to call that function.

1:12:17So I'm going to call main at the very bottom of this file.

1:12:20All right, let's try it out.

1:12:21Python of sayings.py, Enter.

1:12:24And indeed, I see Hello world and Goodbye world.

1:12:26And so I think it's reasonable for me to assume

1:12:28that these functions, albeit simple, are pretty correct at this point.

1:12:32But now, suppose that I want to use these functions as though I've indeed

1:12:36created my own library, my own Python module and that makes available

1:12:40a Hello function for me or anyone else who wants to use

1:12:42it or a Goodbye function as well.

1:12:44Well, let me go ahead and open up again say.py but start fresh.

1:12:49And rather than have the cow say anything, let me go ahead

1:12:52and have my own library do the talking.

1:12:55So I'm going to go ahead and as before, import sys so that I

1:12:58have access to command line arguments.

1:13:00And from my own module called sayings, I'm going to import Hello.

1:13:05So because I created a file called sayings.py, I can say from sayings.

1:13:10And it's inferred by Python that I mean sayings.py,

1:13:13at least in this current directory.

1:13:14But I specifically ain't going to import just one of the functions

1:13:17for now, namely Hello.

1:13:19And now, I can do something like this.

1:13:20If the user obliges by giving me two command line arguments, which

1:13:24I can check by just checking the length of sys.argv,

1:13:27I'm going to then go ahead and call this new Hello function passing

1:13:32as its input, sys.argvbracket1, which should hopefully be the person's name

1:13:36which I'm going to expect them to type at the prompt.

1:13:38So here we go.

1:13:39I'm going to go down to my terminal window,

1:13:41run Python of say.py and my own name because I want my own name to end up

1:13:46in the command line arguments and therefore, be part of the Hello

1:13:49so when I hit Enter in just a moment, I should hopefully see Hello,

1:13:52comma, David.

1:13:53So here we go, Enter.

1:13:55And huh, I see Hello world, Goodbye world.

1:13:59And then I see Hello, David.

1:14:01So why is this happening?

1:14:04Well, it turns out even though I've done everything

1:14:06according to our own past practice, it's not really

1:14:10the right way to go about calling main after all.

1:14:13If I'm blindly calling main here at the bottom of my file, that

1:14:17means whenever this file is loaded by Python, main is going to get called.

1:14:20And unfortunately, that's true even if I'm importing this file or just

1:14:25a function from this file as I am here in my say.py program.

1:14:29This is to say on line three here, when I say from sayings,

1:14:32import Hello, this effectively tells Python

1:14:34to go find that module, sayings.py, read it from top to bottom, left to right,

1:14:39and then import specifically the Hello function.

1:14:41Unfortunately by the time Python has read the file from top

1:14:44to bottom, left to right, that last line of code recall is to call main.

1:14:49Main gets called no matter what.

1:14:51So really, the right way to go about using a main function, which

1:14:55does solve that problem of ensuring that we can order our functions

1:14:58however we want, and all the functions will

1:15:00be defined at the time they're invoked, I

1:15:03shouldn't be unconditionally calling main at the bottom of this

1:15:06or really any of my programs.

1:15:08I should instead use this technique.

1:15:09I should say if__name__=="__main__", then and only then should you actually

1:15:22call main.

1:15:23Well, it turns out that this variable is a special symbol in Python, __name__.

1:15:30And notice that VS Code because of its font

1:15:32isn't quite showing those two underscores.

1:15:34But they're indeed there to the left and the right.

1:15:36This is a special variable whose value is automatically set by Python to be,

1:15:40quote, unquote, "main" when you run a file from the command line

1:15:45as by running Python of sayings.py.

1:15:48So watch what happens now with this additional conditional in sayings.py.

1:15:52If I run Python of sayings.py, it still works as before because name will be

1:15:59automatically set to __main__ when I run this file using Python of sayings.py.

1:16:07But notice this.

1:16:09Name is not going to be set to, quote, unquote, "main."

1:16:12It's going to be set to something else, technically the name of the module

1:16:15when I instead import the file like I do here.

1:16:19So this highlighted line of code even though it

1:16:21will cause Python to go find sayings.py, read it from top to bottom,

1:16:25left to right, it's going to ignore the call to main this time

1:16:27because it's wrapped in that conditional.

1:16:29In this case, when I'm importing a file and not running it directly

1:16:33at the command line, main will not get called

1:16:36by definition of that names value.

1:16:38So let me go ahead and try this.

1:16:40Instead of running Python of sayings.py, which

1:16:42is the module, which contains that conditional main,

1:16:45let me go ahead here, run Python of say.py,

1:16:49which is the program here before me that imports Hello from sayings.

1:16:54But because of that conditional, it's not

1:16:56going to say Hello to anyone else except me in this case.

1:17:00All right, we're here at the end of our week.

1:17:02It's only appropriate, I think, to import something other than Hello.

1:17:06Why don't I go ahead and import not Hello, but Goodbye from here.

1:17:09Let me go ahead and call Goodbye instead of Hello.

1:17:12And this time when I run Python of say.py,

1:17:15I'm not going to type my own name.

1:17:16Allow me if I may to type in the whole world

1:17:18so that our final sentiment today is Goodbye world.

1:17:22Indeed, that's it for this week.

1:17:23We will see you next time.

Recently added transcripts

Browse the whole transcript library

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