Search code examples
pythonslicemagic-methodstypechecking

What is the pythonic/faster way to check if the "key" argument of a custom __getitem__ method is a slice?


I have a custom Sequence type. It is essentially a wrapper for a list plus a boolean flag and I wanted it to emulate usual immutable sequence behavior.

My issue is with slicing. I understand that in Python 3 the way to implement it is to have a __getitem__(key) method that returns an item if %key is a single index and a sliced sequence if %key is a slice object. But how should I discriminate these cases?

I basically have two hypotheses.

sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
    return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list

But this is evil, isn't it? Or

sliced_list = self.wrapped_list[key]
try:
    return MyCustomSequenceType(sliced_list, boolean_flag)
except TypeError:
    return sliced_list

The latter looks more pythonic. It relies on the fact that MyCustomSequenceType.__init__(self, datas, flag) calls len(datas), it so raise TypeError if %datas is an integer. But then, if __init__ raises TypeError for another random issue it will be untraceable. Also http://wiki.cython.org/enhancements/numpy/getitem hints that isinstance is faster (in fact more easily optimizable).

What should I do, then?


Solution

  • You could have a look through the standard library and copy what is done there. For example, calendar.py has:

    def __getitem__(self, i):
        funcs = self._months[i]
        if isinstance(i, slice):
            return [f(self.format) for f in funcs]
        else:
            return funcs(self.format)
    

    which shows both explicit checking with isinstance and partially ducking the issue by simply passing the index or slice through to the underlying list.