[MUSIC PLAYING] SPEAKER: Well, hello, one and all. And welcome to our short on dictionaries. Now, dictionaries are useful when you want to store similar kinds of information in terms of these key-value pairs. So more on that in a moment, but let's first dive into our scenario here. I have here a program called report.py, where the goal is to write a report on some given spacecraft that's out there in the universe. And notice how here I have a function called create_report() that takes as input something called spacecraft, an argument here called spacecraft. And my goal is to, well, one, hopefully make sure this report actually has the information I'm looking for and then return that report for printing, perhaps up in main() over here. Now, we said that dictionaries are good for storing collections of related information. And I think a spacecraft kind of qualifies in this sense. A spacecraft has something like a name, maybe a distance from Earth, let's say. So I think a spacecraft could be good to represent with a dictionary. Well, let's try this out here. I'll go head up to main() here, and I will create our very first spacecraft. I'll call, in this case, just spacecraft. And I'll set spacecraft equal to, well, a dictionary. And so we've seen that a dictionary begins with these curly braces. Whereas a list begins with square brackets, a dictionary is noted with these curly braces here. Now, a dictionary, of course, comes with these keys and values. Now, a key is simply some name, so accessing some particular value inside of this dictionary. And maybe the first key we should have here is some attribute of our spacecraft-- maybe its name, for instance. So I'll say here one of our keys is "name." And syntax-wise, what I have to do when I specify a key is this. I give the name of the key. In this case, the name of the key literally is "name." I can then type colon followed by the value I hope for this key to represent. So in this case, maybe let's talk about Voyager 1, which is the furthest manmade spacecraft, really, any kind of object, away from Earth, "Voyager 1" here. So here our spacecraft is a dictionary. And we have one key, "name," that is assigned the value "Voyager 1." But, of course, there are more really properties of Voyager 1 we can actually put inside of this dictionary. One of them is distance-- "distance." And we said Voyager 1 is the furthest manmade object from Earth. So we'll go ahead and say that this is 163 Astronomical Units away, which is on the order of, let's say, billions of miles away. Go ahead and look up what that conversion is on your own. So here we have Voyager 1, and we also have a distance of 163 AU. And this together forms our spacecraft. So if I want to create a report on this spacecraft, I could, as we said before, maybe print the result of create_report() but then give as input our spacecraft down below. And hopefully, if we run python report.py-- hmm. Well, we see a report. I argue that create_report() is returning us some text, and we're printing it in main(). But we haven't fixed these TODOs. So we have here our own dictionary with keys and values that we have specified. But if we want to access those values, given some key, well, we can do that, perhaps, in create_report(). Now, in general, we could assume, let's say, that create_report() is given some spacecraft that is a dictionary with these two keys, "name" and "distance." And the goal here is really to just access the values at those keys. So I could use here our Python f-string and use curly braces of my own. These are not curly braces for a dictionary. These are curly braces for interpolating some value. I can put in Python code here to get some value and actually incorporate it into this text called REPORT here. So for the name of our spacecraft, we know we have a dictionary that's called spacecraft being passed as input to create_report(). And we also know, and we can assume in this case that this dictionary will have a key called "name," all lowercase. So to access the value at this key, we can use brackets followed by the actual key of our-- actual name of our key. In this case, the name of our key literally is "name." So here, to be clear, what we'll do is go ahead and interpolate some value inside of this f-string. And this value will be the value we access by accessing the name-- the key name-- as part of our spacecraft dictionary here. Let's do the same thing now for distance. We can assume that our spacecraft dictionary also has a key called "distance" just like this. And now, if we were to rerun this report, I think we'd see that we get a report back with our name being Voyager 1 and our distance being 163. But there are no units here. So let's go ahead and actually add this in-- 163 AU, or Astronomical Units. All right. So this is our report. And you get a sense for how handy these things like dictionaries can be. We are able here to combine various pieces of information-- the name of our spacecraft, the distance-- and then access it very easily using these keys that we have down below. Now, what might go wrong with dictionaries? Well, let's say we're not using Voyager 1 anymore. We're using a new spacecraft, or more specifically, a kind of telescope called the James Webb Space Telescope, one of the most recent space telescopes created that can help us see far beyond the reaches of space. So here I'll make a new dictionary, and I'll set the name to "James Webb Space Telescope." But I'm actually not quite sure how far away this telescope is from Earth. So I'll leave that key empty here. Well, I can go ahead and try to run python of report.py. But before I do, maybe think about what might go wrong when I call create_report(). Let's see here. I'll hit Enter. And I'll actually get what's called a key error down below. I see key error, colon, 'distance.' And it seems to me that we tried to access this key named "distance" in create_report(), but our assumption was not quite correct. Spacecraft does not have a key called "distance." So let's go ahead and add that key here. Well, it turns out that to add a new key to a dictionary, I don't need to just simply create it as a dictionary is being built. I could also do this. I could go ahead and try to do spaceraft, bracket, "distance," much like the syntax down below, to access this key, but then supply some value. In this case, I could say that it is, I think-- let me just check here-- it is 0.01 AU away from Earth. So actually, interestingly, the James Webb Space Telescope kind of orbits the sun in a kind of constant distance around from Earth-- so about 0.01 AU here. Let's go ahead and run this report again. I'll say python of report.py, and now we'll see that our report has been fixed for us down below. So we've seen here various ways to add keys to dictionaries, various ways to access those keys and to create our own dictionary. Let's consider more ways to actually access these values for a given key. Let's go back a little bit and assume we actually don't have this value, 0.01. We have just here the key "name." What could we do to perhaps, maybe, anticipate this error and make create_report() a little more flexible with the kinds of input it might get? Well, it turns out that to access some key, we don't need to always use this bracket notation. In fact, there is some other method, one called get, we can use to try to access some key. And if that key doesn't exist, we'll actually get some other value we specify instead. So here, perhaps in "distance," I could, instead of using bracket "distance" here, I could use dot get. So the name of my dictionary, spacecraft, dot get, followed by the key I hope to access in my dictionary, in this case, "distance." I could, if I wanted to, supply another value that will actually be returned if this "distance" key is not part of my dictionary. And we saw earlier that "distance" is not part of this dictionary. So what we should hopefully see instead is "unknown." Why don't I go ahead and try python of report.py, hit Enter, and now we'll actually see that get returned to us "Unknown" instead of the actual value for this nonexistent key. This avoids the key error we saw earlier as well. So let's try this here. I'll do spacecraft.get, and I'll try to get the name of the spacecraft. Otherwise, we can go ahead and return "Unknown" as well. So in general, you'll find that most of the time, you can use that same bracket notation we saw earlier. But if you aren't sure if some key will exist, you could use get to try to get that key but return some other value if that key in fact, does not exist inside of your particular dictionary in this case. So I believe this gives us an example of how we can go ahead and get our keys. Let's now explore other ways to add keys beyond just the same syntax we saw earlier as well. So recall we could go ahead and add in a key by creating a dictionary up here. I could say "distance"-- "distance," colon, et cetera, here. I could even do some syntax like this-- spacecraft "distance" equals, let's say, 0.01. These are two ways to add keys to a dictionary. It turns out there's also one more to be familiar with as well. If I wanted to add not just one key at a time to my dictionary, but maybe multiple at once, I could use a method called update. So I could type the name of my dictionary followed by a dot and then update, just like this. And update takes as an argument, as an input here, another dictionary. But it will really take that dictionary's keys and values and just add them to the dictionary I started with here-- in this case, spacecraft. So it will update spacecraft with all of the keys and values that I provide as input to update. Now, I could go ahead and specify here in another dictionary maybe the distance, which we said before was 0.01 AU. And then we can maybe specify another attribute, maybe the orbit here. As we said before, the James Webb Space Telescope orbits the sun in this case. So here, I'm trying to add now two new keys, one called "distance" and one called "orbit," each with their own values. I could also go down below here, and I could add in some new line of my report. Maybe I'll say "Orbit," and that is equal to maybe spacecraft.get the key called "orbit." Otherwise, we'll return "Unknown" if that key perhaps doesn't exist down below. All right. So here we've tried to add here two new keys at once to our dictionary up above. Let's go ahead and run python of report.py. And now we'll see that those keys are in fact, part of our dictionary thanks to update as well. So now we've seen how to add keys in various ways, how to access keys in various ways. But let's see some other utility features of dictionaries as well. I'll actually go ahead and remove what I have here. And why don't we try to make a new program, one called distance.py? Now, in distances.py, we're going to treat dictionaries a little bit differently. I'm going to make a dictionary where I have the names of my spacecraft in one column, if you will, and the distances of those spacecraft in another column, if you will, in my dictionary. So, for instance, I can make a dictionary called distances and open up some curly braces here. And as the keys in this dictionary, I'll go ahead and have the names of spacecraft, like "Voyager 1," for instance. Now, the value of this particular key will be the distance that Voyager 1 is away from Earth, which happens to be 163 AU, as we saw before. Now, I can go ahead and add other keys to my dictionary, other spacecraft and their distances. I can also go ahead and add "Voyager 2," which happens to be 136 AU away from Earth. I could go ahead and add "Pioneer 10," which is about 80 AU away, "New Horizons," another probe, which is about 58 AU away, and, finally, "Pioneer 11," which is about 44 AU away. So notice how here, my dictionary is representing multiple spacecraft, but I'm really defining the relationship between my spacecraft names and their distances as well. So with my information represented like this, I could try to maybe print out each of their names and their distances using some key functionalities of dictionaries here. I'll go ahead and define myself a function called main(), and I'll leave that empty for now. I'll go down below and make sure I call main(). And now, within main(), my goal is to, for each spacecraft I have inside of this dictionary, print out its name and the distance away from Earth. So if I wanted to do something for each, let's say, anything I have, a good idea is to use a for loop. In this case, I want to do something for each key I have in my dictionary. Well, it turns out that dictionaries come with a method called keys that returns to me all the keys in my dictionary. So I could type for name in distances.keys(). And, again, dot keys, this method here, that will return to me all of the keys in my dictionary-- so first "Voyager 1," then "Voyager 2," then "Pioneer 10," "New Horizons," "Pioneer 11." These will all be part of the return value of dot keys when called on the distances dictionary. And now I'm saying for name in that list of keys. So first name will be equal to "Voyager 1," then "Voyager 2," then "Pioneer 10," as my for loop continues in the code indented here on line 12. So now that I have name, which will first be "Voyager 1," "Voyager 2," I might also want to access, in this case, the distances of those probes from Earth. And to do that, I could actually maybe plug in my key to my dictionary and get back the value I'm looking for. Let's demonstrate this here. I'll type print(), and I'll use an f-string. And I'll then say "name"-- referring to the name of my spacecraft-- "is" and then some distance away from Earth. But, again, we have here "name," which is in fact, a key of our dictionary. So I could type "distances," bracket, "name," to access the value for each of these various keys I'm getting. For instance, when name is equal to "Voyager 1," I'll get back 163 right here. When name is equal to "Voyager 2," well, I'll get back 136 right down here. So I could complete the sentence by saying name is some distance in AU from Earth, just like that. Let's go ahead and try running this. I'll say python of distances.py. And we'll see here some other reports on our spacecraft. Voyager 1 is 163 AU from Earth. Voyager 2 is 136 AU from Earth. So when you want to do some kind of code, like this on line 12, for each key in your dictionary, you could use dot keys to access each of those keys and loop over them, perhaps, with something like a for loop. One more to be familiar with here-- you can also loop over, let's say, the values in our dictionaries. So just like we have keys, we also have values as well, dot values. And let's try maybe converting these AU to meters instead, a much more friendly unit of measurement. So I'll go ahead and replace this code down below here. And why don't I actually delete this for loop here and first give myself a function to convert AU-- to convert AU into, in this case, meters? And it turns out that the number of meters corresponding to 1 AU is this big number here. I'm not even sure how to pronounce it, but I will make sure to type it in correctly-- 597870700. And I believe this is correct-- 870, 597, 149. Yes. This really big number that I don't know how to pronounce is the number of meters in 1 given AU. So if we wanted to perhaps loop over all of our values in the dictionary-- so first 163, then 136, then 80 and so on, we could use a for loop. I could say for, perhaps, distance in distances.values. And then I could perhaps print using an f-string the distance in AU is the converted distance in meters. So to be clear here, a function called convert() that takes an amount of AU and converts it to meters-- then, in main(), we go through each value in our dictionary's values, and then we'll go ahead and convert that distance to meters and also print out the distance in AU. So I'll go ahead here and I'll run python of distances.py. And now we'll hopefully see down below all of these distances in AU now in meters. So we've seen a lot about dictionaries. We've seen, back in report.py, how to create them, how to supply keys and values. We've seen how to update our dictionaries, whether using the update method or by using bracket notation we saw a little earlier too. We've seen how to access those values given some key. We've seen the get method down below as well as the more simple bracket notation, too. And over in distances.py, we've seen how to loop over the keys and the values in our dictionaries. That's it here for our short on dictionaries. We'll see you next time.