8

I read something about slice in Python 3. Then I wrote a program, tried to implement __getitem__(self, slice(s)). Code goes below:

class NewList:
    def __init__(self, lst):
        print('new list')
        self._list = lst
    def __getitem__(self, x):
        if type(x) is slice:
            return [ self._list[n] for n in range(x.start, x.stop, x.step) ]  #error?
        else:
            return self._list[x]
    ...

nl1 = NewList([1,2,3,4,5])
nl1[1:3]  #error occurs

Then I found out x.step is None, which made range raise an exception. So, how should I implement the __getitem__ method?

2
  • Also, your NewList class should inherit from list... Commented Aug 17, 2011 at 3:48
  • @JBernardo --Do u mean that I should avoid using slice objects explicitly? Commented Aug 17, 2011 at 3:59

4 Answers 4

6

You need to use the slice.indices method. Given the length of your sequence, it returns a tuple of start, stop, step:

>>> s = slice(2, 5, None)
>>> s.indices(10)
(2, 5, 1)

>>> [x for x in range(*s.indices(10))]
[2, 3, 4]

>>> s.indices(3)
(2, 3, 1)

>>> s.indices(0)
(0, 0, 1)
Sign up to request clarification or add additional context in comments.

2 Comments

Where can we find documentation om the slice class?
4

In the case where you don't know the length of your object there is an obvious trick to circumvent this mandatory parameter. For example an infinite sequence's getitem can look like this:

  def __getitem__( self, key ) :
    if isinstance( key, slice ) :
       m = max(key.start, key.stop)
       return [self[ii] for ii in xrange(*key.indices(m+1))]
    elif isinstance( key, int ) :
       #Handle int indices

It will only fail if you don't give start and stop but with checking for None this could be handled too.

1 Comment

xrange doesnt exist in python3, instead we should use range. also using this implementation you can't have slices like [:4] because max can't handle None type. Instead you should check if start and stop are not None, and if they are, assign them to zero and len of items, respectively. Also, it's good to include key.step in range, too.
1

If x is a slice, you can do the same as the other condition:

return self._list[x]

3 Comments

absolutely yes, but I just want to know how to do it myself
@Alcott, not sure what you mean by "do it myself".
sorry, I mean I want to know how the __getitem__(self,slice) implemented in list.
0

how about x.step or 1?

class NewList:
    def __init__(self, lst):
        print('new list')
        self._list = lst
    def __getitem__(self, x):
        if type(x) is slice:
            return [ self._list[n] for n in range(x.start, x.stop, x.step or 1) ]  #error?
        else:
            return self._list[x]

nl1 = NewList([1,2,3,4,5])
nl1[1:3]

1 Comment

ya, it's way circumventing the problem, but according to what I read, no.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.