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开发者_StackOverflow I do, then?
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.
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...).
精彩评论