Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing fancy indexing in a class

Tags:

python

Some libraries like numpy, pandas or even python lists implement fancy indexing for its objects. This means I can do things like:

obj[1:3, :]

If I want to offer this functionality in my class I could try to overload the __getitem__ and the __setitem__ methods:

class Example(object):
   def __getitem__(self, x):
      pass

but I don't see how this could work as 1:3 is not a valid variable name. How can this functionality be achieved?

like image 782
elyase Avatar asked Sep 09 '13 00:09

elyase


2 Answers

Slices like 1:3 are turned into slice objects and passed to your function. If you have multiple indexers, they are turned into a tuple. To demonstrate:

>>> class Example(object):
...     def __getitem__(self, index):
...         return index
... 
>>> example = Example()
>>> example['hello']
'hello'
>>> example[1:5]
slice(1, 5, None)
>>> example[1:5, 10:15]
(slice(1, 5, None), slice(10, 15, None))
like image 76
icktoofay Avatar answered Oct 13 '22 00:10

icktoofay


The only thing special about the slice notation is the shorthand for slice, which makes your code equivalent to:

obj[(slice(1, 3), slice(None, None))]

The parameter passed to __getitem__ is the "index" of the item, which can be any object:

def __getitem__(self, index):
    if isinstance(index, tuple):
        # foo[1:2, 3:4]
    elif isinstance(index, slice)
        # foo[1:2]
    else:
        # foo[1]
like image 43
Blender Avatar answered Oct 12 '22 22:10

Blender