Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 858
Evpok Avatar asked May 19 '11 09:05

Evpok


2 Answers

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.

like image 117
Duncan Avatar answered Nov 15 '22 18:11

Duncan


That should be isinstance(key, slice), not isinstance(key, "slice").

Also, you shouldn't call __getitem__ directly - use the [] item notation.

For myself, I would use the isinstance(key, slice) method if I needed to discern - slice is a pretty special thing, not something that's easily going to be replaceable with another type (think about it - if self.wrapped_list is a list, a slice is the only type of object which will return other than an element or error).

So I'd end up with it like this:

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

Consider further though whether you need to treat slices specially; I have no idea what your case is, but when making an architectural decision which will influence things later, it's generally a good idea to consider a few different ways of doing the same thing and evaluate them all and decide on the best one (not that I do it much myself - I tend to just rush in and implement and patch afterwards...).

like image 44
Chris Morgan Avatar answered Nov 15 '22 18:11

Chris Morgan