Implementing slicing in __getitem__
Sometimes, we need to implement slicing functionality in our own class. Below is an example using slicing to get the installed Python version (copied from six.py, a Python2 and 3 compatibility library):
import sys
PY34 = sys.version_info[0:2] >= (3,4)
Here, sys.version_info
contains (major, minor, micro, …). By using [0:2]
, we get a tuple (major, minor), such as (2, 7) for Python2.7.3.
To support slicing, we need to use object.__getitem__(self, key)
method. The key
could be an integer or slice objects. For example,
>>> class A(object):
... def __getitem__(self, key):
... print key
...
>>> a = A()
>>> a[0]
0 # an integer
>>> a[0:2]
slice(0, 2, None) # a slice object
>>> a[0:4:2]
slice(0, 4, 2) # a slice object of (start, stop, and step)
>>> a[0,4,2]
(0, 4, 2) # a tuple as index, which is out of our scope today
That is to say, a call a[0:2]
is equivalent to a[slice(0,2,None)]
.
With this in mind, we can customize our slicing as below:
class Seq(object):
def __init__(self, seq):
self._seq = seq
def get_value(self, i):
pass
def __getitem__(self, key):
if isinstance(key, slice):
start, stop, step = key.indices(len(self))
return Seq([self[i] for i in range(start, stop, step)])
elif isinstance(key, int):
return self.get_value(key)
elif isinstance(key, tuple):
raise NotImplementedError, 'Tuple as index'
else:
raise TypeError, 'Invalid argument type: {}'.format(type(key))