[MUSIC] In this video, we're going to take a look at a few different issues that can arise with keys in dictionaries. In particular, we'll look at how you can determine if a key is actually mapped in a dictionary and how you might go about protecting yourself when you're accessing a dictionary and you're not sure if the key is actually going to be in the dictionary. So, let's take a look. We can use pythons in operator to determine if the key is mapped within a dictionary. To do this, we first need a dictionary obviously, and so I've created one called mapping here that has five key value pairs. The keys and values all happen to be integers in this dictionary, but that doesn't matter, it has no relevance here. We can do this with any kind of dictionary with keys of any type and values of any type. So first, let's look if these keys are in the dictionary. I'm asking is 1 in mapping and is 8 in mapping? And we can see that those are both keys in that mapping dictionary. So I would expect this to be true for both of them. And it is, in fact, True. Now, you need to realize that in is testing for keys not values in the dictionary. So let's take a look when we use in on some values. Both 5 and -3 are values in this dictionary, but they are not keys. So 1 is mapped to 5 and 8 is mapped to -3. So you might expect this to return True, because they are in the dictionary. But in, as I just said, is checking if it is a key in the dictionary. So we get False in both of these cases. Now what about something that is both a key and a value? Well, maybe that's a little bit confusing, but if you think about it for a little bit, it's not. It's checking is 22 a key in the mapping, and the answer to that question is yes, so they should be evaluate to True. The fact that it's also a value is pretty much irrelevant, and in fact it does evaluate to True. All right, and now look at something that is neither a key nor a value. We've already seen that if it's not key we're going to get False. So the fact that it's not a value shouldn't really change that, and I would expect this to evaluate to False. And in fact it does. Now let's look at one way in which we might use in to protect ourselves from errors. Let's imagine that we have a list of numbers. And we believe that list contains numbers that are all keys in our dictionary and we'd like to print out all the key value pairs. So you can imagine iterating through the list and printing the key and then mapping bracket key, that should print the key and the associated value. Well, let's see what happens. Okay, not all of those numbers are actually keys in the dictionary. And the first one that we hit that's not a key is 14. And so we get a KeyError, so this is not going to work, right? Instead, we need to be a little bit more clever, right? Let's actually use in to protect ourselves, so that we will only actually look up the value for keys that are in the dictionary. So here you can see again I'm iterating over all the keys in that keys list, but first, I have an if statement here where I say if key in mapping. Then I know it's a key, then I can print out the key and mapping said key. If it's not, I know it's not a key, so I'm going to print out a message saying, hey, this is not in the mapping, right? And hopefully this will work better for us, and in fact it does. So for the keys that are in the dictionary, 8, we get 8 and -3, and 22, we get 22's mapped to 17. Then the keys that are not in the dictionary, we get our nice error message that 14 and 25 are not in the mapping. Now finally, I want to show you some issues that you might run into with dictionaries. I very highly recommend that when you create a dictionary you always use the same type for all of the keys within that particular dictionary. So if you're going to use integers as keys in your dictionary, all of the keys should be integers. If you're going to use strings, they should all be strings. Now Python doesn't force you into this, okay? So here I've created a mapping where I have a key that is a floating point number, 4.0, a key that's a string, the lower case letter a, and a couple of keys that are Booleans, True and False, all right? And let's print out this mapping, okay? And we can see there's no problem with that, Python is perfectly happy, okay? Now, let's update the values that are associated with some of these keys. So I want to change the mapping of 1 to be associated with 7. Well, there is no key 1, so this should create a new mapping from 1 to 7 in the dictionary, and that's what I would expect. Presumably, that's what you would expect, too. But, let's run this program. What happened? There is no new mapping from 1 to 7. Instead, you might notice here that True, which used to be mapped to the string True, is now mapped to the value 7, why? Well, Python uses equality to determine if two keys are the same. And in Python, you should try this, 1 and True are equivalent, [LAUGH] okay? And so when you try to add a mapping from 1 to 7, instead of doing that it says, I already have the key that's equivalent to 1, which just happens to be called True. I'll just update it to be 7. All right, let's see what happens here when I try to add a new mapping from the key 0 to the value which is a string false. Again, there's no key of 0 here, so I would expect this to add a new key value parent to our mapping. Let's take a look at what happens. [SOUND] No, yet again it did not do that. Python considers 0 and False to be equivalent. So when I tried to add a mapping with the key 0, it said I already have an equivalent key, which just happens to be called False. I'll update its value to be the string false. All right, how about this time? I want to create a mapping from the integer 4 to the integer 7. Well, the integer 4 is not a key in this dictionary. At this point I'm guessing you've caught onto my tricks here, and you can guess what's going to happen. You got it, all right, let's check. [SOUND] It did not add a new mapping from 4 to 7, rather it says hey, I've already got a key that's equivalent to the integer 4. It just happens to be the floating point number 4.0, and then updated the value that was mapped to 4.0 from 2 to 7. [LAUGH] All right, what about this last one? There is no mapping with a key that is the string, which is an uppercase A, but we do have a lowercase a. What's going to happen here, can you guess? Did I trick you, maybe, [LAUGH] this did add a new mapping. The string that is the lower case a is not the same as the string that is an upper case A. So it did add a new mapping from the key, which is the string a to the value which is the string abc. The in operator is very valuable in that it allows us to figure out if a particular key is actually mapped in a given dictionary. You just have to remember it's only checking the keys, you can't use the in operator to learn anything about the values that are in a dictionary. But, that is still very valuable. And I've shown you one way in which you can use that in operator to make your code a little bit safer, in that you don't access a dictionary with a particular key, unless you know that that key is mapped within the dictionary. And I also showed you some of the idiosyncrasies of Python and how it treats keys and dictionaries, and just be careful with that, all right? Like I said, your dictionaries, all the keys should be the same type.