Python 3, an Illustrated Tour Transcripts
Chapter: Language syntax
Lecture: Unpacking Generalizations
0:00 In this video, we're going to talk about additional unpacking generalizations. This came out in pep 448 which is in Python 3.5.
0:09 The pep reads extend usages of the * iterable unpacking operator and ** dictionary unpacking operators to allow unpacking
0:17 in more positions an arbitrary number of times. Let's look at some examples here. If I had a dictionary and I wanted to merge it with another one
0:27 in Python 2 and prior to Python 3.5 I would have to do something like this. I would create a dictionary here called thing_colors
0:36 which is mapping some object to the color. So apple is red, pumpkin is orange. And if I wanted to merge this into a new dictionary with more colors
0:45 one way I could do it is create the new dictionary here called more_colors and then I could say update more colors with thing_colors
0:52 that would insert thing_colors into more colors. And then I could update more colors with other values there,
0:58 note that in this case apple I'm overriding it with green. This pep allows us to do something like this
1:04 where I say thing_colors is equal to apples is red and pumpkin is orange and more_colors is equal to,
1:11 and then I make a literal dictionary but inside of that I put ** thing_colors in there.
1:16 What that does is it unpacks the keys and values from that dictionary and copies them into more_colors.
1:22 After that, I'm going to insert bike is blue and apple is green, note that apple here is a repeated key
1:29 and so because this apple comes after, where after means further to the right in my literal dictionary here, then this apple mapping to green
1:39 will overwrite the apple that is red. But note that in more colors here, I have pumpkin as orange in there.
1:48 Also note that Python 3.6 the order of dictionary insertion is remembered apple was the first key that I put in followed by pumpkin
1:58 and note that in more colors apple is first, pumpkin is second and then bike is third,
2:02 because this key was already in there, it stayed in the first position, even though the value is updated.
2:08 So an unpack can be in any location in the dictionary in the previous example, it was at the very start
2:13 but it can be at the end or you can have actually multiple unpacks in a dictionary Here I say bike is blue, apple is green
2:22 and then we're going to unpack thing_colors in there, in this case the apple that's red from there overrides the apple that is green.
2:30 But note that bike and apple are in first and second position because they were in the original dictionary. Another nice feature of this change is
2:40 it allows us to have multiple ** operations in function calls here. Note that here I'm calling this function print args,
2:47 which takes variable number of keyword arguments and I'm saying I want to pass in thing_colors unpacked and also more_colors unpacked.
2:56 This one didn't work prior to Python 3.5, but in Python 3.5 and above you can do syntax like this
3:02 and note that I'm putting in another named parameter here with a value in between those.
3:08 One thing to be aware of though, is that you can't repeat names in a call. So this might be a gotcha here.
3:14 Here I've got thing colors and I've got apple is red here, I've also got more colors apple is green
3:20 and if I call this with thing_colors and more_colors with these repeated keys, I get a type error. In the prior example on the previous slide,
3:28 I didn't repeat that apple key and so I didn't get this error. So this is something you might need to be aware of if you're repeating those.
3:35 Simple way to get around that is just to merge those dictionaries before calling them in there, that's something that might happen.
3:42 So that's the ** operation that allows us to unpack into dictionaries and also use unpacking and function calls in more than one place if we want to.
3:52 Let's look at the single star, single star allows us to create tuples. So here I've got name is equal to Matt.
3:59 Remember that the string Matt is a sequence of characters here. And if I say *name, with a comma at the end here, it's going to give me back a tuple.
4:11 Note that I'm not doing this extended unpack operation, there's no assignment here, so this is slightly different than the prior examples
4:19 where I would get back a list, but this is saying I want you to take what's in the sequence and stick it into a tuple.
4:25 This is also a case where you might need a comma if I have name is equal to Matt and I just say *name on itself,
4:32 I get this error here, syntax error, can't use a star expression here. Here, I've got some examples of various ways we can use star expressions
4:40 and know that by default, these return a tuple and I can actually string these together by putting a comma
4:47 and use multiple of them and here I have a tuple, note that there's parentheses here with all of the characters from name and last in there,
4:56 if I wanted to put those into a list, I just put square brackets around those and that puts it into a list.
5:04 Similarly, I can put it into a set, note that a set is not ordered, so the order comes out a little different than what the order is in name and last.
5:13 Here I've got a little function called summer that just takes variable arguments and variable keyword arguments
5:18 and it's going to sum all the arguments that are passed in in positional locations and it's also going to sum all the values
5:25 so it's not doing very much, it just accepts arbitrary number of arguments and sums them if they are positional or values in keyword arguments,
5:34 let's look at some examples of calling this, I can call it with 1, 2, 3, any number of positional arguments and it gives me 6.
5:41 I can also call it with star list here and then a three following that, and that's fine, Python 3.5 and above doesn't complain about that.
5:51 Note that I can also have multiple stars here and this can be a list here, it can be any sequence here, and I can have
5:59 however many stars I want to in that, if I want to, and here I'm calling it with a star, a positional parameter
6:04 unpacking a dictionary here, a keyword parameter here and another unpacked dictionary over here and that works as well.
6:14 Little bit of the difference between this syntax and the extended unpacking that we showed in another video,
6:20 here I've got name is equal to the string Matt. I can do the extended unpacking by doing an assignment here on the left-hand side
6:27 by saying *letters, I need the comma at the end there is equal to name that makes a new variable called letters
6:34 and it is a list with the individual characters in it. Note that in this unpacking generalization,
6:40 which is different than the extended unpacking defined in this pep here, I am not putting this on the left-hand side,
6:46 I need to put it on the right hand-side, I put a star in front of it, a comma at the end
6:51 and I assign it to a variable and it gives me back a tuple here. So a little bit of a difference between those two,
6:57 if you need to create a list you can use this extended unpacking. Note that if I simply put square brackets around that
7:05 I will also get a list on the second example. This video talked about additional unpacking generalizations, which is pretty cool.
7:14 If you want to create dictionaries from other dictionaries or merge dictionaries or create tuples or lists or sets from sequences,
7:22 you can easily do this with this new syntax. You can also pass in multiple unpacking operations into function calls, which is cool as well.