Chapter 4: More iterable objects

enumerate

face Josiah Wang

We will take a break from your robot project a bit and explore some useful built-in iterables in Python. Iterables are objects that can be used as part of a for-loop. For example, range and list are iterables. In case you have not realised it yet, range is actually a class, not a function!

Getting both indices and elements together

Say you want to print out the top 5 songs from the UK Top 40 charts.

[The Official UK Top 40 chart for 15th October 2021-21st October 2021]

# Title
1 Cold Heart
2 Shivers
3 Love Nwantiti
4 Boyz
5 Heat Waves

And you are given the songs in the form of a list.

>>> top_hits = ["Cold Heart", "Shivers", "Love Nwantiti", "Boyz", "Heat Waves"]

You can naturally use a for-loop to iterate over a list.

>>> for title in top_hits:
...    print(title)
...
Cold Heart
Shivers
Love Nwantiti
Boyz
Heat Waves

This will only give you the song titles, without the chart positions. To obtain the chart position, you can either have a counter that increments inside the loop, or you can iterate over the range object and access the title from the list via indices (as below). Remember to add 1 to position when printing it out!

>>> for position in range(len(top_hits)):
...    print(f"At number {position+1} we have {top_hits[position]}!")
...
At number 1 we have Cold Heart!
At number 2 we have Shivers!
At number 3 we have Love Nwantiti
At number 4 we have Boyz!
At number 5 we have Heat Waves!

This feels like extra work though. Can we actually get both the index and the song title at the same time?

The answer is yes! You can do this with the enumerate object.

>>> for (position, title) in enumerate(top_hits):
...    print(f"At number {position+1} we have {title}!")
...
At number 1 we have Cold Heart!
At number 2 we have Shivers!
At number 3 we have Love Nwantiti
At number 4 we have Boyz!
At number 5 we have Heat Waves!

If having to manually add 1 to position is a hassle (and this might also be hard to read), you can provide an optional second argument to enumerate’s constructor to tell it to start the index at 1.

>>> for (position, title) in enumerate(top_hits, 1):
...    print(f"At number {position} we have {title}!")
...
At number 1 we have Cold Heart!
At number 2 we have Shivers!
At number 3 we have Love Nwantiti
At number 4 we have Boyz!
At number 5 we have Heat Waves!

Note that the parenthesis before position and after title is optional. So the following is equally valid.

for position, title in enumerate(top_hits, 1):
    print(f"At number {position} we have {title}!")