Doubt about the Slice function

Asked

Viewed 778 times

1

To the answer back that one question that the Guilherme Nascimento P. did, opened up a doubt on the use of the function slice, until the moment I had no knowledge of it, and to find it in the documentation got confused.

Researching here on Sopt I found nothing about it, the terms used in the search were: [python] Slice function and [python] Slice.

Our friend @jsbueno commented:

the Python "function" Slice mentioned in the first paragraph is not used as indicated. It only builds an "Slice" object that is used internally to pick up sequence sessions, as explained in the rest of the answer. In general it is only used if you are implementing a sequence class that works as a list.

My question is: How is the correct use of the function slice ?

input = [ 'laranja', 'limão', 'melancia', 'mamão' ]
print(input[slice(1,-1)])

Obs.: As for the question tags, if any are missing just let us know.

2 answers

4


The call built-in slice Python is not really a function - like some other Python calls, it’s actually a class that creates the object slice.

The chances of you needing to use slicedirectly are quite small, but there are some uses - in general more for you to check whether an object is a slice and use it, than to create one directly.

The Slice object is what is used internally by Python when using "slice notation" (Slice Notation) to delimit a subset of a sequence, such as a list or a string.

This notation is nothing more than using numbers separated by : within a pair of brackets [ ] used as an index - how do we:

In [70]: a = "banana"

In [71]: a[1:4]
Out[71]: 'ana'

Or

In [72]: b = list(range(10, 20))

In [73]: b
Out[73]: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

In [74]: b[:-5:2]
Out[74]: [10, 12, 14]

(in that case, the slice [:-5:2] should be read as: take the sub-sequence from the beginning, up to 5 positions before the end, counting from 2 in 2).

As you probably know, all operations on Python objects are translated internally for calls to "magic" methods that have a predefined name - the best documentation for these methods is the 'data model" of the language, at this address: https://docs.python.org/3/reference/datamodel.html

In particular, when we get, do an assignment or delete (with the command del) a sub-sequence within a sequence Python calls respectively the methods __getitem__, __setitem__ and __delitem__ of the object class representing the sequence.

In this process, Python transforms the numbers placed in the slice notation between brackets into an object slice. That is, Python itself calls the "function" slice for us.

The object slice in turn is quite simple, we can view the documentation or introspect it using the dir:

In [75]: a = slice(1, 4)


In [76]: dir(a)
Out[76]: 
[...
 'indices',
 'start',
 'step',
 'stop']

(i deleted the magical methods of Slice because they are not important) - if you look at "start", "step" and "stop", they correspond to the attributes we passed to the beginning and end of the sequence, and "None" to step (step), which is the third optional argument)

The method indices requires an integer to represent the size of the sequence - and all it does is, taking into account the length of the sequence passed as parameter, compute the start, end and step indices already taking into account the omitted parameters (i.e., left blank before or after the :), negative indices, etc... The values returned by the call to the methodindice can be used directly in the "function" range to generate all the indexes of that slice.

It’s easier to visualize with an example: let’s create a subclass of list that always returns all the elements of a slice transformed into strings:

class StringSliceList(list):
    def __getitem__(self, indices):
         if isinstance(indices, slice):
              results = []
              start, stop, step = indices.indices(len(self))
              for i in range(start, stop, step):
                   results.append(str(super().__getitem__(i)))
         else:   
            results = super().__getitem__(indices)
         return results

Okay, with that we can play in the interactive terminal:

In [84]: a = StringSliceList(range(20))

In [85]: a[5:10]
Out[85]: ['5', '6', '7', '8', '9']

The object Slice can be passed directly between brackets, but it will always be less readable than using directly the notation with ":":

In [86]: a[slice(5,10)]
Out[86]: ['5', '6', '7', '8', '9']

I believe that your maintenance as a built-in by default Python is more of a slip-up than anything else - it’s a class that could very well be in the module types. But as this was in the transition to Python 3, it is also something very little important to break compatibility, so it gets.

Trivia:

In the case of a multi-dimensional index, where several axes are separated by , inside the brackets, as used in Numpy matrices, each component separated by , can be converted to an object slice separate.

class Test:
   def __getitem__(self, indices):
       print(indices)

Can be used:

In [89]: Test()[1:10, :, -1:5:10]
(slice(1, 10, None), slice(None, None, None), slice(-1, 5, 10))

And that doesn’t happen if you put an extra pair of () inside the [], because it creates a tuple that doesn’t have the components converted to objects of the type slice:

In [90]: Test()[(1:10, :, -1:5:10)]
  File "<ipython-input-90-32002bdbab86>", line 1
    Test()[(1:10, :, -1:5:10)]
             ^
SyntaxError: invalid syntax

-1

Slice into a list would be the equivalent of using: ":"

input = ['laranja','limão','melancia','mamão']
print(input[1:-1])

There are numerous ways you can delimit a list. See this question in the stack in English, they explain very well the use of Slice:

Understanding Python’s Slice Notation

  • sorry for the downvote, but the question is about the built-in slice not on the Slice Notation .

  • Good, I got it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.