Title: Learn some value unpacking tricks in Python
This example explains how you can easily unpack lists of values in Python.
If you set multiple variables equal to something that contains multiple values, Python is happy to match them up. For example, the following code assigns the two values 20 and 30 to the two variables x and y.
x, y = 20, 30
That's a pretty handy technique for assigning multiple values at once, but it becomes more powerful when the thing on the right extracts the values from something complex instead of just including hard-coded results.
Saving Pieces
The following code stores the pieces of a string in two variables.
names = 'Zaphod Beeblebrox'
first_name, last_name = names.split()
print(f'{first_name};{last_name};')
The first statement defines a string containing two words. The right-hand side of the second statement calls the string's split method to split the string into a list of words. The program then assigns the list's two values into two variables. The final statement displays the following output.
Zaphod;Beeblebrox;
To use this technique, the number of items on the left must match the number of items on the right. If you don't have enough variables on the left, you'll see something like ValueError: too many values to unpack. If you have too many variables, you'll get ValueError: not enough values to unpack.
That's somewhat awkward if you don't want to use all of the values, but there's an easy workaround: just assign every value to a variable. You can then ignore any variables that you don't want.
Here's an example.
animals = 'Aardvark Bonobo Caracal Damselfish Egret Flamingo'
first, second, third, fourth, fifth, sixth = animals.split()
print(f'{first};{second};')
This code declares a string containing six words. It then uses split and the basic variable assignment technique to save the words into variables. The code then ignores all but the first two values to produce this output.
Aardvark;Bonobo;
Obviously you can ignore any of the values, not just the first two. For example, you could print out the second, fourth, and sixth values and ignore the rest.
Less obvious is the fact that you can use the same variable name multiple times on the left. In that case, Python gives the variable the value that matches with the last instance of the variable. Consider the following code.
first, second, last, last, last, last = animals.split()
print(f'{first};{second};{last};')
This code assigns the first two values to variables first and second. It then assigns last to each of the remaining values sequentially so it ends up holding the final value. Here's the result.
Aardvark;Bonobo;Flamingo;
Unwanted Values
The previous example saves the values Caracal through Flamingo all in the same variable last so it can easily ignore the values Caracal through Egret. It works but is a bit confusing because last is assigned multiple times when we really only want the final value.
A slightly better approach would be to save every value in separate variables and then ignore the ones we don't need. Even that can be a bit bewildering, though, because all of those variables (perhaps with names like unused1, unused2, and so forth) are assigned and left floating around to cause confusion.
Python provides a better approach: give any unwanted values the underscore for a name. Python still doesn't really care and it happily creates a variable named _, but that name tells you and others who read your code that you plan to ignore that value. Here's an example.
first, _, third, _, _, _ = animals.split()
print(f'{first};{third};')
This code saves the first and third values in named variables. All of the other values are dumped into _ and then not used. (Your code can actually use the variable _, but that defeats the purpose of this convention so don't do it.)
Skipping Multiple Values
The preceding example lets you ignore values in a way that makes it pretty clear which values you will ignore. It's a little clunky, however, because you still need to include _ for every value that you want to ignore. That's an even bigger problem if you don't know how many values you'll want to skip. For example, suppose you're reading a file where each line represents a customer order. A line contains a customer's name, date, and a list of items purchased and each order might include a different number of items. Now you can't assign a variable to each item because you don't know how many there are.
Fortunately there's a solution to this little dilemma. If you place an asterisk before a variable, Python places any number of values inside it. Here's an example.
first, *_, penultimate, last = animals.split()
print(f'{first};{penultimate};{last};')
In this case, Python saves the first value in first, skips several values for *_, places the second-to-last value in penultimate, and puts the final value in last. Here's the output.
Aardvark;Egret;Flamingo;
How does Python know how many values to put in the _ variable? It matches the other values that don't have an asterisk and then assigns the remaining values to _. That means you can have only one asterisked variable in the expression. Otherwise Python wouldn't know how many values to assign to each.
Here's how you might read the customer name from a line in the orders file described earlier.
first_name, last_name, order_date, *_ = line.split()
Conclusion
Most Python programmers learn how to assign multiple variables at the same time fairly early on. Fewer know how to use the same variable multiple times and how to use underscores to represent values that you will ignore. And even fewer know about using * to capture multiple values at once.
Download the example to experiment with it and to see additional details. Then use these techniques to make your code easier to write and understand.
|