Why Pack or Unpack Values?
Python developers may unpack, or pack values to compensate for the unknown length of values in an iterable or unknown key/value pairs in a dictionary.
iterable may be either a sequence, a container that supports iteration, or an iterator object. (Python Docs)
As an example, let's say that a function named getStudentInfo()
returns a list with the student information and the letter grades that the student has received in different classes.
["Taylor", "Science", "A", "B", "B", "A", "C"]
# name, major, letter grades
The function always returns the name and major, but students take a different number of classes. Thus, we can't rely on the same number of grades in the list. To handle this variability, we can unpack the values.
>>>
in the code examples, it means I am using Python's IDLE. >>> def getStudentInfo():
return ["Taylor", "Science", "A", "B", "B", "A", "C"]
>>> name, major, *grades = getStudentInfo()
>>> name
'Taylor'
>>> major
'Science'
>>> grades
['A', 'B', 'B', 'A', 'C']
This example is small, but it sheds light on how we assigned the:
- First value in the list to the variable
name
- Second value to the variable
major
, and; - used
*
(an asterisk) to gather all the remaining values into a list namedgrades
In the next sections, let's take a look at how unpacking and packing vary across iterables, dictionaries, and functions.
Unpacking Values: Iterables vs. Dictionaries
Unfortunately, we can't unpack dictionaries in the same way that we can target variations in list values.
Let's replay our example from earlier, but use a dictionary for information instead.
>>> def getStudentInfo():
return {"name": "Taylor","major":"Science", "Biology": "A", "Music in the Humanities": "B", "Genetics": "B"}
>>> name, major, *grades = getStudentInfo()
>>> name
'name'
>>> major
'major'
>>> grades
['Biology', 'Music in the Humanities', 'Genetics']
# We just get the keys
More Iterable Unpacking
Depending on your version of Python, you could also target your *
to grab values in the middle of a list.
>>> example = ["first", "in", "be", "tween", "last"]
>>> first, *inbetween, last = example
>>> first
'first'
>>> inbetween
['in', 'be', 'tween']
>>> last
'last'
Functions: Unpacking & Packing
We can pack values and deliver them as a function's arguments, again, with a slight difference between iterables and dictionaries. Then, the function can unpack the values and use them.
Iterable
Below is an example of how we can pack values into a function that takes positional arguments.
>>> def authorInfo(name, rating):
print(name + ' has a rating of ' + str(rating))
>>> author = ["Jarrett", 1000]
>>> authorInfo(*author)
Jarrett has a rating of 1000
The values from author
are spread as the arguments in the order they appear in author
.
Dictionary
We can use the same function above to demonstrate how this works with a function that takes keyword values.
First, we define the function using keyword arguments. Then, we assign the author
values inside of a dictionary. However, instead of passing the author
variable into the function with one *
we use two **
.
>>> def authorInfo(name="", rating=0):
print(name + ' has a rating of ' + str(rating))
>>> author = {"rating": 1, "name": "Jarrett"}
>>> authorInfo(**author)
Jarrett has a rating of 1
The order of the values in the dictionary is different from the order in the function declaration, but the values are still assigned properly.
**kwargs
The **kwargs
function parameter is born from unpacking an arbitrary amount of values. I see this used a lot in matplotlib . The graphing functions have the option to take many layout parameters that can be defined in a dictionary.
Imagine the function call matplotlib.hist(data, **kwargs)
. This function plots a histogram and then takes an arbitrary number of named keyword arguments. Utilizing these arguments may look like:
matplotlib.hist(data, color="blue, ls="---")
The required data
parameter is passed in, but color
and line-style (ls
) are optional.
This was only a brief introduction to packing and unpacking values. You can read more about this Python feature in the Python Docs.