getitem and slices
In Python, you can override square brackets operator ([]
) by defining __getitem__
magic method.
The example is Cycle
object that virtually contains an infinite number of repeated elements:
class Cycle:
def __init__(self, lst):
self._lst = lst
def __getitem__(self, index):
return self._lst[index % len(self._lst)]
print(Cycle(['a', 'b', 'c'])[100]) # prints 'b'
The unusual thing here is []
operator supports a unique syntax.
It can be used not only like this — [2]
, but also like this — [2:10]
,
or [2:10:2]
, or [2::2]
, or even [:]
.
The semantic is [start:stop:step]
but you can use it any way you want for your custom objects.
But what __getitem__
gets as an index
parameter if you call it using that syntax?
The slice objects exist precisely for this case.
In : class Inspector:
...: def __getitem__(self, index):
...: print(index)
...:
In : Inspector()[1]
1
In : Inspector()[1:2]
slice(1, 2, None)
In : Inspector()[1:2:3]
slice(1, 2, 3)
In : Inspector()[:]
slice(None, None, None)
You can even combine tuple and slice syntaxes:
In : Inspector()[:, 0, :]
(slice(None, None, None), 0, slice(None, None, None))
slice
is not doing anything for you except simply storing start
, stop
and step
attributes.
In : s = slice(1, 2, 3)
In : s.start
Out: 1
In : s.stop
Out: 2
In : s.step
Out: 3