Python double color with -1 as third parameter

As an example, take a = [1,2,3,4,5] . In my instinct, I think a[::-1] matches a[0:len(a):-1] . But the result is wrong:

 >>> a = [1,2,3,4,5] >>> print a[::-1] [5, 4, 3, 2, 1] >>> print a[0:len(a):-1] [] >>> print a[0:3:-1] [] >>> print a[0:2:-1] [] >>> print a[:2:-1] [5, 4] >>> print a[:0:-1] [5, 4, 3, 2] >>> print a[0:-1] [1, 2, 3, 4] 

In fact, I can not understand the last 6 attempts to withdraw. Can someone give me some idea? Thank you tons.

+7
python
source share
3 answers

The syntax to be used is [start:end:step] , where the end is not included.

Python follows some rules, which are based on what is probably implied (it is possible that they are not what you had in mind, but in this case the developers can get the final results). We will review the exact rules below.

a[::-1] is a shortcut to change the list. If we say to work backward without any restrictions, we probably want to go from end to start.

a[0:len(a):-1] means start from scratch, and by -1 go to len (a). Note that this is not possible (we just end up with an infinite number of negative numbers), so the result is empty. a[0:3:-1] and a[0:2:-1] have the same problem.

In the last example, a[0:-1] negative index means the last element. You are probably going to go from start to finish. Please note that the endpoint is not included. This gives everything except the last element (which can also be specified as a[:-1] ).

With a[:2:-1] you specify a backward movement, so you probably want to go back from the last item to index 2. This gives [5,4] in your example. Case a[:0:-1] similar, but the movement starts from the beginning, giving [5,4,3,2] .


Referring to the cpython source code , we can see the actual rules.

  • If the step is not specified, it is 1
  • If the initial value is not set, select the initial start as 0 if the step is not negative, or length -1 if it is
  • If the end value is not set, select the default value as the length if the step is not negative or -1 if it (these values ​​allow you to save the last element, knowing that the end point is not included)

Some settings are performed at the start and end values, if specified

  • If the value is less than 0, add the length to it.
  • If it is even less than 0, set it to 0, if the step is non-negative, otherwise set it to -1
  • If it is greater than or equal to the length, set it to one less than the length, if the step is negative or equal to the length, otherwise

Note that in most cases, rules define values ​​that can be specified exactly to get an equivalent form. An exception is when the default rule defines the start or end point -1. If we give this value, the rules for changing values ​​will change it.

Applying these rules, we obtain

  • a[::-1] uses beginning of length-1 (default), end -1 (default) and step -1
  • a[0:len(a):-1] , a[0:3:-1] and a[0:2:-1] use the given values
  • a[:0:-1] uses the start of length-1 (default), end 0 and step -1
  • a[:2:-1] uses the start of length-1 (default), end 2 and step -1
  • a[0:-1] uses start 0, end-1 (changed), and step 1 (default)

At this point, we can determine if a choice is possible. In the case of empty, since the step is negative and we start <end, now we see that this is impossible.

+10
source share

When there are three parameters, this indicates a step. That is, -1 means that step 1 goes backward. That is why when your first argument is less than the second, you get an empty list.

In the case of two parameters, it indicates the last item counter from the end.

If you leave the first parameter empty, Python will again take the second as an index to the end of the range and start counting from the end, since the step is negative.

+1
source share

For an explanation of the results of your various attempts, see Matthew anser .

Between the lines of your question, though, I read that you want to replicate the behavior of a[::-1] , but explicitly passing in the start and stop slice.

The Python tutorial will take a closer look at the lines that mention this useful mnemonics:

One way to remember how slices work is to consider indices as pointing between characters, with the left edge of the first character being numbered 0. Then the right edge of the last character is a string of n characters with index n, for example:

  +---+---+---+---+---+---+ | P | y | t | h | o | n | +---+---+---+---+---+---+ 0 1 2 3 4 5 6 -6 -5 -4 -3 -2 -1 

The first line of numbers gives the position of the indices 0 ... 6 in Struna; the second line gives the corresponding negative indices. The slice from i to j consists of all the characters between the edges indicated respectively by i and j.

Of course, the same line rules apply to other sequences, such as lists and tuples. The textbook does not mention [1] this means that for negative steps you need to work with shifted indices indicating between For example:

  β”Žβ”€β”€β”€β”°β”€β”€β”€β”°β”€β”€β”€β”°β”€β”€β”€β”°β”€β”€β”€β”°β”€β”€β”€β”’ ┃ P ┃ y ┃ t ┃ h ┃ o ┃ n ┃ <== For backwards slicing (ie negative step) β”žβ”€β”€β”€β•€β”€β”€β”€β•€β”€β”€β”€β•€β”€β”€β”€β•€β”€β”€β”€β•€β”€β”€β”€β”¦ 0 1 2 3 4 5 -7 -6 -5 -4 -3 -2 -1 

This is because indexes do not actually indicate between elements of a sequence. Rather, the cut stop parameter is an exceptional boundary, i.e. The resulting sequence ends with the last element spanned by step , before who has the stop index.

From this shifted pseudo-index table, it can be seen that in order for the whole sequence to be reversed by cutting with explicit boundaries, we must start with len(a) - 1 (or higher). We also see that there is no non-negative index that we can use as stop , and still have the first element of the original sequence, included as the last element of the resulting sequence. [len(a)-1:0:-1] will end already in the second source element. And we cannot use -1 as stop , as it is a short hand to refer to the position after the last element independent of len(a) . We should use -len(a) - 1 as stop (or lower) instead:

 >>> a[len(a)-1:-len(a)-1:-1] [5, 4, 3, 2, 1] 

If you explicitly specify the boundaries explicitly, this is probably why they can be adapted if only a part of the sequence should be used in a later version of the code. In order for the code to be adapted, it is necessary to revise the current audit so that you can make an informed decision about what needs to be changed. Needless to say, a[len(a)-1:-len(a)-1:-1] much less clear than list(reversed(a)) , which can easily be supplemented with borders:

 >>> list(reversed(a[2:4])) # referring to indices of original sequence [4, 3] >>> list(reversed(a))[1:3] # referring to indices of reversed sequence [4, 3] 

[1] The reason why this tutorial does not mention this is probably before Python 2.2 the possibility of using a step where cutting can only be used for NumPy sequences (and possibly other third-party sequences), but is not supported by the list of Python built-in sequences, tuple and string. Python 2.3 added an implementation of this extended slice semantics for built-in sequence types.

+1
source share

All Articles