Write Pythonic Code Like a Seasoned Developer Transcripts
Lecture: Merging dictionaries
0:01 Next, let's talk about taking multiple dictionaries and combining them into one that we can use to look up items that came from various places.
0:09 Here in PyCharm, I have a sort of web example for you, imagine that you are writing a web app,
0:15 there is data coming from different locations into your action method, so on one hand we have routing setup that is passing data through the URL,
0:23 we might be in that location, passing the id and the current value might be this, the title might be that, we also might have the query string
0:31 and the query string might have some other value for id, like 1, it might have a separate value it's adding to the mix here called render_fast is True,
0:39 then maybe we are also, as part of posting long URL which matches the route with the query string we are posting back a form
0:46 and that form has email, a name and it is well. So here I am just going to print out these three dictionaries
0:52 just so you can see what they look like, and no surprise, here they are, they just look like basically they are written here,
0:58 so what if I want one dictionary that I can just ask - "what is the id, what is the user name or what is the email address?" -
1:07 and not have to worry about which one is located and we have our super non-Pythonic way here and I am going to use this dictionary called "m1",
1:16 we'll go like this, and I'll say "for k in" and what we are going to do is we are just going to loop over each dictionary and stick the value in there.
1:24 The order in which we do this matters. So let's suppose we want the query string that has the least value,
1:29 so we are going to put those values into this combined dictionary first, so we'll say like so, and then we could just go to "m1"
1:35 and we can just set the value for whatever the key is, to whatever the value and the query dictionary, here's like that.
1:45 And, we'll do the same thing for let's say the next thing we are going to do is the post, like that, and finally, we'll do it for the route.
1:56 OK, so if we run it, we should get a dictionary because the route has higher priority,
2:00 with id 27, title Fast apps, render_fast is True and then that data in it. Let's run it, all right, id 271, like we expected, Jef, Fast apps, perfect,
2:12 so it looks like you combined it well, but this is a very procedural way, and there is better ways,
2:17 so in Python down here we can actually sort of improve upon this by leveraging a couple of methods on the dictionary,
2:25 so we can go like this, and remember we wanted the query first so we can say "query.copy" and actually create a copy of the dictionary
2:32 and then we can go here and we can say update, I would like you to update your values possibly overwriting them with "post",
2:38 and then I would also like to overwrite this with the route. So now if I run it, we should have the exactly the same output
2:45 but a little safer, less fiddly. OK, you can see these are the same dictionary, now notice there is nothing about dictionaries that are ordered,
2:54 so they are going to be out of order but they are the same value, down here this "no", I wrote some code that checks
3:00 whether these four dictionaries "m1", "m2", "m3" and "m4" are the same. We are not finished yet, so they are not going to be the same.
3:09 But in the end, we write these better versions here, we should be good. We can actually do this in one line with the dictionary comprehension,
3:15 it's not pretty but it does work. So, let's imagine where they end, we can say "for d in"
3:23 and we can put all of our dictionaries in the order we care about, "query, post" and "route" and so for each one of those we can come back here
3:31 and say "we would like the key:value" and we'll go for each one of these, we'll say "for k,v in d.items"
3:43 So here you can see exactly the same dictionary, matching ordering, let's do a little formatting on that.
3:49 OK, so we are looping over all the dictionaries and for each dictionary we are looping over, we are looping over and point out the key
3:57 and the value from the items and then we are creating the dictionary from that.
4:00 So, this works, I really don't like it very much, even though it happens in one line and it feels like oh that must be Pythonic because look at it,
4:08 it's cool and special and declarative. To me it's hard to look at it and not go "oh, I see you are combining those dictionaries",
4:16 so given the choice between the classic Pythonic way and this dictionary comprehension way, I would actually prefer the one above,
4:22 because this is really clear to me what's happening. Maybe that's just me. But in Python 3.5 they introduced a really cool way to merge dictionaries,
4:31 so if we were going call a function, so let's say some function, and we want to take a dictionary and pass it as keyword arguments here
4:40 I could say **query say, if I wanted to pass the values from the query, but they kind of apply that same syntax here to say
4:47 I would like to merge all the values from - let's start with query, all the values from post and all the values form route.
4:56 so this does not work on Python 3.4 and below so be careful. It's only Python 3.5 and above, let's run it and make sure it does what we expect.
5:07 Boom, look at that, there is a last one we just wrote and if we actually do a comparison of the values ignoring order, these are exactly all the same,
5:16 so here we have the super non-Pythonic way, we have the sort of classical way of doing this, leveraging the dictionary features,
5:26 we have the "clever but too clever" in my opinion way of looping over the dictionaries and looping over their key value items and recombining them,
5:36 and then we have the quite sleek Ptyhon 3 way of the **dictionary to unpack them, back into a dictionary.
5:42 And notice, it has the same overwriting process where the id from the query was overwritten by the id from the route because the route came last.
5:51 Let's see that in a graphic. So, here is our three dictionaries and our non-Pythonic way
5:57 we create a blank dictionary and we just loop over all the items and we just start filling it up, very procedural, not amazing.
6:02 But instead, we can use the Python 3 that is 3.5 actually quite high, way of unpacking the dictionary back into a dictionary
6:10 so this **query **post **route becomes a new dictionary. Very nice.