开发者

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

开发者 https://www.devze.com 2023-03-07 04:04 出处:网络
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.

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号