Mastering the Pythonic Square Bracket: The Magic of `__getitem__`
Mastering the Pythonic Square Bracket: The Magic of __getitem__
In Python, we often take for granted that we can access data using square brackets, like my_list[0] or my_dict['key']. This isn’t just “built-in” magic; it is powered by a special “dunder” (double underscore) method called __getitem__.
Understanding this method allows you to create classes that behave like native collections and, as you’ll see, write incredibly efficient sorting logic.
What is __getitem__?
The __getitem__ method defines how an object should respond when you use bracket notation []. When you write obj[key], Python silently converts that into obj.__getitem__(key).
While we usually use this to define behavior in our own classes, we can also tap into the __getitem__ method of existing objects—like dictionaries—to perform some clever tricks.
The Power of Method Passing
Consider a scenario where you have a list of items and a separate dictionary defining their “rarity” or weight. You want to sort your list based on those dictionary values.
Here is a simple Python script to illustrate that point:
inventory = ['Axe', 'Great Sword', 'Stick']
rarity = {
'Great Sword': 98,
'Golden Bow': 92,
'Iron Sword': 80,
'Axe': 33,
'Stick': 5
}
# Using __getitem__ as the sorting key
sort_inventory = sorted(inventory, key=rarity.__getitem__, reverse=True)
# Output the results
print(f"Sorted Inventory: {sort_inventory}")
# Output: ['Great Sword', 'Axe', 'Stick']
print(f"Rarity of Stick: {rarity.__getitem__('Stick')}")
# Output: 5
Why use key=rarity.__getitem__?
When you pass rarity.__getitem__ to the key argument of the sorted() function, you are handing over a bound method.
- Efficiency over Lambdas: This approach is often faster than using a lambda (like
key=lambda x: rarity[x]). Why? Because a lambda creates a brand-new function object in memory and requires Python to create a new local scope for every single item it sorts. - Direct Access: By using
rarity.__getitem__, you are handingsorted()the direct internal method of the dictionary. You skip the overhead of the lambda’s extra function call. - Mechanical Necessity: Internally,
sorted()takes each item from yourinventory(e.g.,'Axe'), passes it into the function you provided inkey, and uses the returned value (33) to determine the sort order.
Pro-Tips for Implementation
- Handling Errors: Remember that
__getitem__will raise aKeyErrorif an item is missing. If your inventory might contain items not listed in your rarity dictionary, consider usingrarity.getas your key instead, which allows for a default fallback value.
By leveraging __getitem__ directly, you move closer to how Python operates under the hood—making your code both faster and more elegant.