A Mysterious Dictionary Expression
00:00 I want to cover a particular Python trick that I guess is a little bit more quirky, but it’ll still lead to some really interesting considerations. So, what I want to talk about today is a really crazy dictionary expression.
00:15 This dictionary expression is pretty surprising, at least it was really surprising to me when I saw it for the first time. Let me just type this out here real quick.
00:24 So basically what we’re doing here is we’re creating a new dictionary and we’re putting in a bunch of keys. And keep those keys in mind, just kind of look at those keys, and maybe you’ll know what’s going to happen when I hit Return and evaluate this expression.
00:41 So, I’m just going to wait for a second. Think about this. What do you think is going to happen when we evaluate this expression? What do you think the outcome of this would be? Like, actually pause the video and think about this for a minute or two and then come back to it. Okay, ready? I’m going to run this now.
00:58
Boom. Okay. So, the result we’re getting here is a dictionary with just one key. It has just one key True
, and the value is 'maybe'
.
01:07
And actually, when we look at the original expression here, that’s kind of surprising, in my books, right? Because, well, the True
key—well, that was the key we put here, and actually the value was supposed to be 'yes'
.
01:21
And then, that 'no'
at 1
doesn’t show up at all. And here, we have 1.0
—the float value—as the key, and this 'maybe'
value for that key now actually shows up here.
01:35 So, this seems like a complete mess. This is a really surprising result. So, I want to untangle that now because it’s going to show you—I think it’s going to help you to a better understanding, or a deeper understanding, of the Python interpreter and how Python works.
01:48 Like, it certainly helped me with that. Well, the first thing we should do here is try to break down how Python processes our dictionary expression here. I’m just going to play through that now.
01:59
So basically, what happens here if we create a new dictionary, let’s just call it xs
. We create a new dictionary, right? Then, we’ll just grab the key and the value, and we’ll assign the value to the key, right? Oh, I didn’t want to type 'value'
—I wanted to type 'yes'
to match that up with the initial example.
02:22 So, what happens here is that we just add all of these keys here and these values, and as we do this, we should end up with exactly the same result, right?
02:38 So, there’s nothing crazy or special about this dictionary expression. It’s just getting evaluated like any other old dictionary expression that you can come up with where Python does exactly this. So, I think that gives us a hint, right?
02:53
Because it kind of makes us realize that, well, as we’re assigning these keys, we’re overriding them, right? Like, the key 1
—the integer 1
—overrides the key True
, and the float 1.0
overrides the other key. Well, I mean it doesn’t really override the key, but it overrides the value, right?
03:13 So, it seems to be taking the key from the first time we set this particular key, and it seems to take the value from the last time we set this particular key.
03:24 I mean, at this point we don’t really know, like, why are these considered all the same key? But it kind of gives us a hunch, right? Like, what could be wrong here? Let’s play Python detective here.
03:32
So, if we’re actually trying to validate this assumption or test this assumption, let’s just compare all of the keys that we’re using here. And actually, Python tells us that True
, 1
, and 1.0
—they’re all considered equal. They’re all considered to be the same key.
03:51 And so that’s the case because Python actually treats Booleans as a subtype of the integer type. And you can dig that up in the Python documentation here, in The standard type hierarchy.
04:04 So when we search for “bool” here,
04:10
you can see here that “The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False"
or "True"
are returned, respectively.” And that’s our explanation, right? That pretty much explains what’s going on here.
04:31
It doesn’t really explain why we’re not ending up with the key 1.0
at the end, but it kind of explains how these keys are getting overridden.
04:39
So, we can see here that as we’re building up this dictionary, we’re overriding the value for that key. And because you might be wondering why we’re still ending up with True
as the value—or like, the name for that key, that is the case because if the keys are considered equal, Python doesn’t actually have to update the object, right? If they’re considered equal, it can just keep the initial object and update the value.
05:08 And so what you end up with, if we play through this again—let’s play through this again. Let’s actually start with a new dictionary here. So, if we play through this again,
05:20
we’re going to say ys[True] = 'yes'
, and we print out ys
. Okay. That makes sense, right? And now, we’re going to say ys[1] = 'no'
. All right.
05:31
What do we expect now? Well, we expect the key to remain the same and it to be overridden with the new value. And now, if we set the key 1.0
to 'maybe'
, then again, we expect to end up with the results that we’ve gotten out of this dictionary expression very early on. So this seems to confirm our theory, here.
05:59 All right! And that dispels most of this magic here. Now, at the back of your head, you might be thinking, “Oh, aren’t Python dictionaries hashmaps, or something?
06:07 Is that what a hash collision is?” Um… sort of. And actually, I’ve got a lot more to say on this topic to really dive down into the hashmap stuff, and really untangle where that comes into play, so check out the book for that.
06:23 There are going to be some pointers for you to dive more deeply into this.
You must own this product to join the conversation.