使用片表示法反转列表

例如:

foo = ['red', 'white', 'blue', 1, 2, 3]

Where: foo[0:6:1]将打印 foo 中的所有元素。但是,foo[6:0:-1]将省略第1个或第0个元素。

>>> foo[6:0:-1]
[3, 2, 1, 'blue', 'white']

我知道可以使用 foo.return ()或 foo [ : :-1]反向打印列表,但是我试图理解 foo [6:0:-1]为什么不打印整个列表?

106137 次浏览

Slice notation in short:

[ <first element to include> : <first element to exclude> : <step> ]

If you want to include the first element when reversing a list, leave the middle element empty, like this:

foo[::-1]

You can also find some good information about Python slices in general here:
Explain Python's slice notation

...why foo[6:0:-1] doesn't print the entire list?

Because the middle value is the exclusive, rather than inclusive, stop value. The interval notation is [start, stop).

This is exactly how [x]range works:

>>> range(6, 0, -1)
[6, 5, 4, 3, 2, 1]

Those are the indices that get included in your resulting list, and they don't include 0 for the first item.

>>> range(6, -1, -1)
[6, 5, 4, 3, 2, 1, 0]

Another way to look at it is:

>>> L = ['red', 'white', 'blue', 1, 2, 3]
>>> L[0:6:1]
['red', 'white', 'blue', 1, 2, 3]
>>> len(L)
6
>>> L[5]
3
>>> L[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

The index 6 is beyond (one-past, precisely) the valid indices for L, so excluding it from the range as the excluded stop value:

>>> range(0, 6, 1)
[0, 1, 2, 3, 4, 5]

Still gives you indices for each item in the list.

This answer might be a little outdated, but it could be helpful for someone who stuck with same problem. You can get reverse list with an arbitrary end - up to 0 index, applying second in-place slice like this:

>>> L = list(range(10))
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> (start_ex, end) = (7, 0)
>>> L[end:start_ex][::-1]
[6, 5, 4, 3, 2, 1, 0]

If you are having trouble remembering slice notation, you could try doing the Hokey Cokey:

[In: Out: Shake it all about]

[First element to include: First element to leave out: The step to use]

YMMV

Use

>>>foo[::-1]

This displays the reverse of the list from the end element to the start,

Complement. to reverse step by 2:

A = [1,2,2,3,3]
n = len(A)
res = [None] * n
mid = n//2 + 1 if n%2 == 1 else n//2


res[0::2] = A[0:mid][::-1]
res[1::2] = A[0:mid][::-1]
print(res)

[2, 3, 2, 3, 1]

You can get it to work if you use a negative stop value. Try this:

foo[-1:-7:-1]

formalizing the answer from andrew-clark a little bit more:

Suppose the list v and v[n1:n2:n3] slice. n1 is initial position, n2 is final position and n3 is step

Let's write some pseucode in a Python way:

n3 = 1  if (n3 is missing) else n3
if n3==0:
raise exception # error, undefined step

First part: n3 positive

if n3>0:
slice direction is from left to right, the most common direction


n1 is left slice position in `v`
if n1 is missing:
n1 = 0   # initial position
if n1>=0:
n1 is a normal position
else:
(-n1-1) is the position in the list from right to left


n2 is right slice position in `v`
if n2 is missing:
n2 = len(x)  # after final position
if n2>=0:
n2 is a normal final position (exclusive)
else:
-n2-1 é the final position in the list from right to left
(exclusive)

Second part: n3 negative

else:
slice direction is from right to left (inverse direction)


n1 is right slice position in `v`
if n1 is missing:
n1 = -1   # final position is last position in the list.
if n1>=0:
n1 is a normal position
else:
(-n1-1) is the position in the list from right to left


n2 is  left slice position in `v`
if n2 is missing:
n2 = -len(x)-1   # before 1st character  (exclusive)
if n2>=0:
n2 is a normal final position (exclusive)
else:
-n2-1 is the ending position in the list from right to left
(exclusive)

Now the original problema: How to reverse a list with slice notation?

L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(L(::-1)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Why?
n1 is missing and n3<0 => n1=0
n2 is missing and n3<0 => n2 = -len(x)-1

So L(::-1) == L(-1:-11:-1)

This is a very good question, and, in my opinion, none of the above answers really answer the question being asked. Partly because an intellectually honest answer may reveal a weakness of Python type system. And the same weakness exists in some other languages.

A more intellectually honest answer would probably be: Python slicing does not generalize well.

Precisely, one can traverse a collection in one direction with collection[begin:end] but collection[end:begin:-1] does not work. It does not work because the first index is 0 but the "index before the first index" is not -1. Thus, collection[end:-1:-1] does not evaluate to what we would legitimately expect.

The [first to include : first to exclude : step] explanation is flawed. If "first to exclude" is the one before the first element, you cannot express it the same way you would in the case that you wanted to include that same first element.

In conclusion, you're not crazy to expect generality, it is just not there.