I have gone through most of the documentation of __getitem__
in the Python docs, but I am still unable to grasp the meaning of it.
So all I can understand is that __getitem__
is used to implement calls like self[key]
. But what is the use of it?
Lets say I have a python class defined in this way:
class Person: def __init__(self,name,age): self.name = name self.age = age def __getitem__(self,key): print ("Inside `__getitem__` method!") return getattr(self,key) p = Person("Subhayan",32) print (p["age"])
This returns the results as expected. But why use __getitem__
in the first place? I have also heard that Python calls __getitem__
internally. But why does it do it?
Can someone please explain this in more detail?
__getitem__(x, i) . The method __getitem__(self, key) defines behavior for when an item is accessed, using the notation self[key] . This is also part of both the mutable and immutable container protocols. Unlike some other languages, Python basically lets you pass any object into the indexer.
Python __str__() This method returns the string representation of the object. This method is called when print() or str() function is invoked on an object. This method must return the String object.
__getitem__ and __setitem__ in Python They are predefined methods that simplify many operations that can be performed on a class instance, like __init__(), __str__(), __call__() etc. These methods are very helpful because they are used in binary operations, assignment operations, unary and binary comparison operations.
Magic methods in Python are the special methods that start and end with the double underscores. They are also called dunder methods. Magic methods are not meant to be invoked directly by you, but the invocation happens internally from the class on a certain action.
Cong Ma does a good job of explaining what __getitem__
is used for - but I want to give you an example which might be useful. Imagine a class which models a building. Within the data for the building it includes a number of attributes, including descriptions of the companies that occupy each floor :
Without using __getitem__
we would have a class like this :
class Building(object): def __init__(self, floors): self._floors = [None]*floors def occupy(self, floor_number, data): self._floors[floor_number] = data def get_floor_data(self, floor_number): return self._floors[floor_number] building1 = Building(4) # Construct a building with 4 floors building1.occupy(0, 'Reception') building1.occupy(1, 'ABC Corp') building1.occupy(2, 'DEF Inc') print( building1.get_floor_data(2) )
We could however use __getitem__
(and its counterpart __setitem__
) to make the usage of the Building class 'nicer'.
class Building(object): def __init__(self, floors): self._floors = [None]*floors def __setitem__(self, floor_number, data): self._floors[floor_number] = data def __getitem__(self, floor_number): return self._floors[floor_number] building1 = Building(4) # Construct a building with 4 floors building1[0] = 'Reception' building1[1] = 'ABC Corp' building1[2] = 'DEF Inc' print( building1[2] )
Whether you use __setitem__
like this really depends on how you plan to abstract your data - in this case we have decided to treat a building as a container of floors (and you could also implement an iterator for the Building, and maybe even the ability to slice - i.e. get more than one floor's data at a time - it depends on what you need.
The []
syntax for getting item by key or index is just syntax sugar.
When you evaluate a[i]
Python calls a.__getitem__(i)
(or type(a).__getitem__(a, i)
, but this distinction is about inheritance models and is not important here). Even if the class of a
may not explicitly define this method, it is usually inherited from an ancestor class.
All the (Python 2.7) special method names and their semantics are listed here: https://docs.python.org/2.7/reference/datamodel.html#special-method-names
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With