Working with data

Day 9: Exercise Solutions

Python Guru with a screen instead of a face, typing on a computer keyboard with a light green background to match the day 9 image.

Here are our solutions for the day 9 exercises in the 30 Days of Python series. Make sure you try the exercises yourself before checking out the solutions!

1) Below is some simple data about characters from BoJack Horseman. Write a for loop that uses destructuring so that you can print each tuple.

main_characters = [
    ("BoJack Horseman", "Will Arnett", "Horse"),
    ("Princess Carolyn", "Amy Sedaris", "Cat"),
    ("Diane Nguyen", "Alison Brie", "Human"),
    ("Mr. Peanutbutter", "Paul F. Tompkins", "Dog"),
    ("Todd Chavez", "Aaron Paul", "Human")
]

For this exercise, the expected output should be like this:

BoJack Horseman is a horse voiced by Will Arnet.

Let's start by doing this without destructuring. This should be getting fairly routine at this stage. We're just iterating over a collection, and accessing values by index.

for character in main_characters:
    print(f"{character[0]} is a {character[2].lower()} voiced by {character[1]}.")

Don't forget to change the case for the characters' species. In the original data, the initial letter is capitalised, but we want it in lowercase for the output.

Now let's convert our loop to use destructuring. We have three values in each tuple, so our loop needs three variables to assign these values to. I'm going to use character, actor, and species.

for character, actor, species in main_characters:
    print(f"{character} is a {species.lower()} voiced by {actor}.")

I think making this change relies highlights how much more readable this destructuring approach is.

2) Unpack the following tuple into 4 variables.

("John Smith", 11743, ("Computer Science", "Mathematics"))

Here we have four pieces of data inside a tuple. The student's name, their student identification number, and their major and minor subjects in that order. These subjects are stored in a second tuple within the main tuple, so we have to account for that when destructuring the collection.

Remember that to destructure nested collections we just need match the structure of the collection we want to unpack.

name, id_number, (major, minor) = ("John Smith", 11743, ("Computer Science", "Mathematics"))

This works the same way if the tuple is stored in a variable:

student = ("John Smith", 11743, ("Computer Science", "Mathematics"))

name, id_number, (major, minor) = student

3) Investigate what happens when you try to zip two iterables of different lengths.

Let's try this with a pair of lists. The type of iterable we use doesn't really matter, so choose whatever you look.

I'm going to have a list of three letters, and a list of two numbers.

letters = ["a", "b", "c"]
numbers = [1, 2]

Now let's see what happens when we pass these two lists to zip. Remember that zip is lazy, so we're going to have to convert the result to a list or tuple to print any meaningful output.

letters = ["a", "b", "c"]
numbers = [1, 2]

print(list(zip(letters, numbers)))

What we get in the terminal is this:

[('a', 1), ('b', 2)]

What we can see is that zip stopped once we reached the end of the shortest collection. If we have three collections of different lengths, the same thing will happen.

This is a really important detail to keep in mind, because it can lead to accidental data loss if you're not careful.

If you need to ensure that all values end up in the resulting iterable, we have some options which are discussed in the additional resources section of today's post.