Supporting index and key lookups

Share
Copied to clipboard.
Trey Hunner smiling in a t-shirt against a yellow wall
Trey Hunner
2 min. read 1 min. video Python 3.8—3.12

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.

Use __getitem__ to support index and key lookups

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).

A Python Tip Every Week

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