elyase
elyase

Reputation: 40963

Implementing fancy indexing in a class

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?

Upvotes: 6

Views: 835

Answers (2)

Blender
Blender

Reputation: 298166

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]

Upvotes: 5

icktoofay
icktoofay

Reputation: 129011

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))

Upvotes: 7

Related Questions