Supporting index and key lookups

Topic Series: Dunder methods

Trey Hunner smiling in a t-shirt against a yellow wall
Trey Hunner
1 minute read Works on Python 3.7—3.10
Share
Python Morsels
Watch as video
01:25

In Python, you can customize how square brackets ([]) work on your objects.

Index and key lookups both use square brackets

Lists in Python support indexing using square brackets:

>>> colors = ["purple", "blue", "green", "pink"]
>>> colors[1]
'blue'

While dictionaries support key lookups using square brackets:

>>> fruit_counts = {"lime": 1, "apple": 4, "pear": 2}
>>> fruit_counts["pear"]
2

Putting square brackets after an object and passing something into those brackets is called subscript notation. This syntax is powered by the __getitem__ method (pronounced "dunder get item"):

>>> colors.__getitem__(1)
'blue'

Any object that implements a __getitem__ method can be used with that subscript notation:

>>> fruit_counts.__getitem__("pear")
2

So if we want to make our own objects support this subscript notation, all we need to do is make sure we have a __getitem__ method.

Making square brackets work on your objects

This ForgivingIndexer class has a __init__ method and a __getitem__ method:

class ForgivingIndexer:

    def __init__(self, sequence):
        self.sequence = sequence

    def __getitem__(self, index):
        return self.sequence[int(index)]

ForgivingIndexer accepts a sequence and returns an object that can be indexed (which in turn, indexes the given sequence):

>>> colors = ForgivingIndexer(["purple", "blue", "green", "pink"])
>>> colors[1]
'blue'

But we also pass in a string to these square brackets, and our ForgivingIndexer object will convert that string into an integer:

>>> colors["2"]
'green'

Or we could even pass in a floating point number, and it'll convert that into an integer as well:

>>> colors[3.2]
'pink'

It's kind of a "forgiving index" in a sense. This all works because we've implemented a __getitem__ method on our class.

Summary

To allow square brackets to work on your object, you can implement a __getitem__ method. You'll most often see this done in list-like objects (a.k.a. sequences), or dictionary-like objects (a.k.a. mappings).

Topic Trail: Dunder methods

You can overload many operators, protocols, and bits of functionality on your Python objects by implementing dunder methods.

To track your progress on this Python Morsels topic trail, sign in or sign up.

0%
Write more Pythonic code

Need to fill-in gaps in your Python skills? I send regular emails designed to do just that.

Python Morsels
Watch as video
01:25