Unpacking in Comprehensions & Frozen Dictionaries
00:00 In the previous lesson, I demonstrated lazy loading. In this lesson, I’ll show you unpacking in comprehensions and frozen dictionaries. Sometimes, you’re passing data around in a tuple but then want to put the parts of a tuple into individual variables.
00:15
Python lets you do this in a couple of different scenarios, and the process is known as unpacking. A common place you use it is in a for loop, or sometimes when turning a data structure into a function’s arguments or keyword arguments.
00:29 To add some consistency to the language, Python 3.15 now allows you to do unpacking inside of a comprehension. I’ll show you that now. I’ll start by demonstrating regular unpacking, and to do that, I need some data.
00:46
Some letters, and some numbers. In order to have something to unpack, I need something packed. The built-in zip() function pairs values from two collections into tuples.
01:03
zip() returns a zip object, which is why I’ve passed it to a list so you can see the result. Now, I’ll unpack these tuples as part of a for loop.
01:18
The destination part of a for loop can be a tuple like I had done here. When it is, the item from the iterator automatically gets unpacked into those values.
01:28
So the first tuple, ('a', 1), gets unpacked into letter and num, respectively.
01:38
And there you go. Instead of a regular for loop, let me use similar syntax inside of a list to create a comprehension.
01:52 Note that I didn’t use two variables here. It doesn’t quite make sense to have two variables because only one variable is needed, the value being put into the list as part of the comprehension.
02:04
Because I only had the one variable, the result is a list of the packed values. The other way of unpacking a collection is with a * prefix. You sometimes use that to populate the arguments to a function from a list or tuple.
02:16
That would be the *args thing you see once in a while. Unpacking in comprehensions steals this syntax.
02:29
By putting the * prefix in front of our pair value, multiple items are populated into the list comprehension at a time. Each individual part of the pair gets unpacked and put into the list. This is sometimes known as list flattening, and this new syntax means less code is required to flatten a list.
02:49
The companion to *args is **kwargs, and that has been implemented as well for dictionary comprehensions.
03:02
Consider this list of dictionaries. Using ** allows you to unpack key-value pairs and populate the dictionary resulting from the comprehension.
03:15 There are other ways of doing this, like looping over the list and unioning the values, but this new mechanism is more succinct. A frozen object is one that cannot be changed.
03:27
Python already supports some frozen objects, including the frozenset and the tuple, which can act like a frozen list. Python 3.15 adds the frozendict to this collection.
03:38
Off to the REPL. In case you haven’t seen them, let me quickly demonstrate a frozenset.
03:48
Starting with a set of letters. Remember, sets don’t allow duplicates, so my extra "a" is gone. Since it’s a regular set, I can add a value. And there it is.
04:03
You typically instantiate a frozenset based on an existing set. Same content, but a different type. And as you might guess, if you try to add something to a frozen set, you’re told that isn’t allowed.
04:22
Python kind of has a read-only dictionary already called the MappingProxyType. Let me import it.
04:38 And now I’ll create one.
04:45 Like with the frozen set, I create it by passing in an existing dictionary.
04:52
If I try to edit the read-only copy, I get an error. The proxy in MappingProxyType is an important hint, though. This isn’t frozen. It’s only a read-only proxy to the original dictionary.
05:12
the so-called read-only copy gets updated. You can pass someone a MappingProxyType and stop them from mucking with your data, but this is not a frozen object.
05:30 Like with our frozen set, I construct a frozen dict from an existing dict. And there it is. Now, if I try to modify it, I can’t. But unlike with the mapping proxy, changing the source object
05:51 doesn’t modify our frozen object. The creation process is a copy. This is its own thing, not a proxy. One warning, though. It is the reference to the objects that are frozen, not the objects contained within the dictionary.
06:23
I can’t modify the host property because strings are immutable, and I would be attempting reassignment.
06:33
I can modify the list of ports, though. I couldn’t change what the key points to, that would be reassignment, but since it points to a list, I can modify the list without changing what the frozen dict contains.
06:46 It still contains the same list object. This is no different than when you have a list inside of a tuple. For example, you can’t reassign the third item in the tuple, but you can modify a list contained in that position.
07:00 This also has consequences when you’re copying things and a few other edge cases, but as long as you understand the implications of what is frozen in a frozen dict, you’re good.
Become a Member to join the conversation.