Function Argument Unpacking
00:00 There’s a really cool feature in Python that is called function argument unpacking. I’m going to jump right into an example here. I really like this feature because it can make working with your code a lot easier, and it’s not super well known.
00:17 It can seem a little bit arcane, but really when you get to the bottom of it, it’s a really helpful feature, and I think you’ll like this. All right, so what you’ll know at the end of this video is how to use the Python function argument unpacking operators to simplify your code.
00:36
So, the operators I’m talking about here are the asterisk (*
) and double asterisk (**
)—or, I guess “double star”—operator. I want to give you a simple example here.
00:49
So, let’s say we have a function here that lets us print a vector. We just want it to print a nicely formatted vector. So, this is just going to call the print()
function and then I have some format string here that lays out the vector nice and clean so that it’s nice and readable. And we’re just going to pass these components to that string format. And to give you an example of how we might want to call this function…. Let’s see, we have this vector here, a three-component vector, and we’re going to print it and it’s just going to look a little bit nicer, right?
01:29 You know, now we know that’s a vector and maybe we need that for some kind of output format or whatever. It’s a toy example, but I think it still has a bit of a useful purpose here.
01:39 So now, depending on how we choose to represent these vectors in our Python code—in terms of the data structure we use to store these vectors—it can get a little bit awkward if we want to print them. So, let’s say we’ve got our vector stored in tuples, like this…
02:05 or maybe we’ve got them stored in lists, like this.
02:12 Now, if we want to print one of those,
02:15 it actually gets super awkward, because now what I need to do—well, I need to give these indexes manually,
02:25 right? And I can’t really concentrate… like I can’t really talk while I’m typing, so bear with me for a second! So, if I want to print this vector it gets kind of awkward. And sure, I could write a different function that would just take a tuple vector directly, but then what if my vector is going to be represented as a dictionary or as something else? It gets pretty awkward.
02:49 And this is where the function argument unpacking could become really helpful, because function argument unpacking can do something really similar to what we’ve been doing here manually, right?
03:02
Where I was unpacking this tuple manually, there’s actually a shorthand to do that in Python. So what you can do here is if I call print_vector()
function again,
03:15
I can use the star operator (*
), the unpacking operator, and just pass my tuple vector to that print_vector()
function. And this line here is exactly equivalent to this line up there.
03:27 So, when I go ahead and call this, we get the result that we expected, right? Now, the cool thing is this would work in exactly the same way with our list like that, so I can go ahead and, for example, define a generator expression—this is just going to generate a bunch of squared numbers here for us.
03:48 Oh yeah, that was a typo.
03:54
for x in range(3)
, right? So, this is the generator expression that we have here. And now, I can do the same trick on this generator expression.
04:06
And what that’s going to do is it’s going to fully exhaust this generator and then pass it to the print_vector()
function. So this is really handy because now we can transform all of these different data sources and pass it to the same print_vector()
function, and we don’t have to implement, you know, 10 other versions of print_vector()
, but we can reuse the same print_vector()
implementation that we wrote in the beginning. And so it’s a way to match together and connect these different pipes that might not have the same diameter, but we can still connect them with the right adapter, and that is that little *
operator. It’s kind of a crazy analogy, I guess, but that’s maybe a good way to remember how this works. All right, so I mentioned the *
operator, but there is also the **
, or the dictionary unpack operator.
04:55 I want to show you how that works as well. So, let’s imagine we had our vectors represented as dictionaries. Again, I’m just going to put in a bunch of keys here that give a name to these components in the vector.
05:21
All right, and now we’ve got our dictionary vector. And now, of course, we have a problem if we want to pass that to the print_vector()
function, right? Because if I just do this then, well, that doesn’t work. Um…
05:37
can I index this? Not really, right? Like, there’s no key called 0
, so that doesn’t work. However, what we can do here is we can use the double star (**
), or unpacking operator, to unpack this dictionary…
05:55
and it leads to the desired result, right? So, this is pretty much what we expected here. The reason this works is because our print_vector()
function—
06:09 you remember how we defined that earlier—
06:13
it actually had these arguments here that were named x
, y
, z
. So, this is the reason why we can do this. If they were named differently, Python wouldn’t know how to match up these argument names.
06:30 But in this case, it would work nicely. And then, the trouble in general here is that there’s no predefined order to these dictionaries, right? So, we can’t just say, “Oh yeah, you know, take the first key, the second key, and the third key,” because there isn’t really an order to them. It’s random—or, I mean, it’s not random, but it’s arbitrary. Like, depending on the machine you’re running this on, there’s no guarantees on how this is ordered. And, you know, big sidebar—this is going to change in Python 3.6, where dictionaries are going to be ordered by default. For all intents and purposes, you shouldn’t assume that they are ordered.
07:02
So, the only way we can do this is by matching up the argument names here. And to clarify that point on the dictionary argument order—so actually, you might be wondering what happens if I use the list unpack operator to pass this dictionary vector to the print_vector()
function.
07:21
And what you can see here is that we’re getting just the keys, so this is a way to extract the keys, but we’re getting them in random order, right? So this doesn’t really work for that purpose because there’s no order to these keys; like, they’re appearing in a different order than in the initial dictionary expression that we had here. And so that’s why we can use this trick—or like, the only way to use this in a sensible way is to use the **
unpack operator and having these matching argument names. All right. So, you know, you might already notice that there’s a bit of a magic to this, so imagine having to explain this to someone joining your team, like, once a month.
08:09 That would probably be pretty frustrating and so it might not be a technique you want to use in every single Python program that you write. But nevertheless, it’s super important to know about these function argument unpacking operators, because they can be such a great tool, and they can be super helpful.
08:26 And if you apply them within reason—you know, keeping in mind that too much of a good thing can be a bad thing—they can be a fantastic tool in making your Python code more readable and just making you a better, faster, more effective Python programmer.
You must own this product to join the conversation.