Python 列表错误:[::-1] 踩在 [:-1] 切片上

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41430791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:56:35  来源:igfitidea点击:

Python list error: [::-1] step on [:-1] slice

pythonslicereverse

提问by Matt Kelty

I thought I understood the basics of list slicing in python, but have been receiving an unexpected error while using a negative step on a slice, as follows:

我以为我了解了 python 中列表切片的基础知识,但是在切片上使用负步时收到了意外错误,如下所示:

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

(Note that this is being run in Python 3.5)

(请注意,这是在 Python 3.5 中运行的)

Why doesn't a[:-1:-1] reverse step through the a[:-1] slice in the same manner as it does through the whole list with a[::-1]?

为什么 a[:-1:-1] 不以与使用 a[::-1] 遍历整个列表相同的方式反向遍历 a[:-1] 切片?

I realize that you can use list.reverse() as well, but trying to understand the underlying python slice functionality better.

我意识到你也可以使用 list.reverse() ,但试图更好地理解底层的 python 切片功能。

回答by NPE

The first -1in a[:-1:-1]doesn't mean what you think it does.

第一个-1a[:-1:-1]不意味着什么,你认为它。

In slicing, negative start/end indices are not interpreted literally. Instead, they are used to conveniently refer to the end of the list (i.e. they are relative to len(a)). This happens irrespectively of the direction of the slicing.

在切片中,负开始/结束索引不会按字面解释。相反,它们用于方便地引用列表的末尾(即它们相对于len(a))。无论切片的方向如何,都会发生这种情况。

This means that

这意味着

a[:-1:-1]

is equivalent to

相当于

a[:len(a)-1:-1]

When omitted during reverse slicing, the start index defaults to len(a)-1, making the above equivalent to

当在反向切片期间省略时,起始索引默认为len(a)-1,使上面的等价于

a[len(a)-1:len(a)-1:-1]

This always gives an empty list, since the start and end indices are the same and the end index is exclusive.

这总是给出一个空列表,因为开始和结束索引是相同的,结束索引是独占的。

To slice in reverse up to, and including, the zeroth element you can use any of the following notations:

要反向切片直到并包括第零个元素,您可以使用以下任何表示法:

>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a[:None:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a[:-len(a)-1:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

回答by godaygo

When you type [1, 2, 3, ...][1:4:1]it is the same as [1, 2, 3, ...][slice(1, 4, 1)]. So 1:4:1is the shorthand for sliceobject. slicesignature is slice(stop)or slice(start, stop[, step])and you can also use Nonefor arguments.

当您键入时,[1, 2, 3, ...][1:4:1]它与[1, 2, 3, ...][slice(1, 4, 1)]. object1:4:1的简写也是如此sliceslice签名是slice(stop)slice(start, stop[, step]),您也可以None用于参数。

:: -> slice(None, None, None)
:4 -> slice(4)
# and so on

Suppose we have got [a: b: c]. Rulesfor indices will be as follows:

假设我们有[a: b: c]. 指数规则如下:

  1. First cis checked. Default is +1, sign of cindicates forward or backward direction of the step. Absolute value of cindicates the step size.
  2. Than ais checked. When cis positive or None, default for ais 0. When cis negative, default for ais -1.
  3. Finally bis checked. When cis positive or None, default for bis len. When cis negative default for bis -(len+1).
  1. 首先c是检查。默认为+1, 的符号c表示步的前进或后退方向。的绝对值c表示步长。
  2. a被检查。当c为正或None,默认a就是0。如果c是负的,默认a就是-1
  3. 最后b是检查。当c为正或None,默认b就是len。什么时候c是负默认值b-(len+1)

Note 1: Degenerated slices in Python are handled gracefully:

注 1:Python 中的退化切片处理得当:

  • the index that is too large or too small is replaced with lenor 0.
  • an upper bound smaller than the lower bound returns an empty list or string or whatever else (for positive c).
  • 将太大或太小的索引替换为len0
  • 小于下限的上限返回空列表或字符串或其他任何内容(对于 positive c)。

Note 2: Roughly speaking, Python picks up elements while this condition (a < b) if (c > 0) else (a > b)is True(updating a += con every step). Also, all negative indices are replaced with len - index.

注2:粗略地说,而这种情况的Python拾取元件(a < b) if (c > 0) else (a > b)True(更新a += c在每一个步骤)。此外,所有负索引都替换为len - index

If you combine this rules and notes it will make sense why you got an empty list. In your case:

如果您将这些规则和注释结合起来,就会明白为什么您得到一个空列表。在你的情况下:

 In[1]: [1, 2, 3, 4, 5, 6][:-1:-1]        # `c` is negative so `a` is -1 and `b` is -1
Out[1]: [] 

# it is the same as:

 In[2]: [1, 2, 3, 4, 5, 6][-1: -1: -1]    # which will produce you an empty list 
Out[2]: [] 

There is very good discussion about slice notation: Explain Python's slice notation!

关于切片表示法有很好的讨论:解释 Python 的切片表示法

回答by MSeifert

I generally find it useful to slice a range-object (this is only possible in python3 - in python2 rangeproduces a listand xrangecan't be sliced) if I need to see which indices are used for a list of a given length:

如果我需要查看哪些索引用于给定长度的列表,我通常发现对range-object进行切片很有用(这仅在 python3 中可行 - 在 python2 中range生成 alist并且xrange无法切片):

>>> range(10)[::-1]  
range(9, -1, -1)

>>> range(10)[:-1]  
range(0, 9)

And in your last case:

在你的最后一种情况下:

>>> range(10)[:-1:-1]
range(9, 9, -1)

This also explains what happened. The first index is 9, but 9 isn't lower than the stop index 9 (note that in python the stop index is excluded) so it stops without giving any element.

这也解释了发生了什么。第一个索引是 9,但 9 不低于停止索引 9(请注意,在 python 中,停止索引被排除在外)所以它停止而不给出任何元素。

Note that indexing can also be applied sequentially:

请注意,索引也可以按顺序应用:

>>> list(range(10))[::-1][:-1]  # first reverse then exclude last item.
[9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> list(range(10))[:-1][::-1]  # other way around
[8, 7, 6, 5, 4, 3, 2, 1, 0]

回答by John B

sliceworks similar to rangein that when you make the stepargument a negative number, the startand stoparguments work in the opposite direction.

slice工作原理类似于range当您使step参数为负数时,startstop参数以相反的方向工作。

>>> list(range(9, -1, -1)) == a[::-1]
True

Some examples that may help make this more clear:

一些可能有助于更清楚地说明这一点的示例:

>>> a[6:2:-2]
[6, 4]
>>> a[0:None:1] == a[::]
True
>>> a[-1:None:-1] == a[::-1]
True
>>> a[-2:None:-1] == a[:-1][::-1]
True

回答by Ash

Python's slices seem fairly simple at first, but their behaviour is actually quite complex(notes 3 and 5 are relevant here). If you have a slice a[i:j:k]:

Python 的切片起初看起来相当简单,但它们的行为实际上相当复杂(注释 3 和 5 在这里是相关的)。如果你有一个切片a[i:j:k]

  • If ior jare negative, they refer to an index from the end of a(so a[-1]refers to the last element of a)
  • If ior jare not specified, or are None, they default to the ends of a, but whichends depends on the sign of k:

    • if kis positive, you're slicing forwards, so ibecomes 0 and jbecomes len(a)
    • if kis negative, you're slicing backwards, so ibecomes len(a)and jbecomes the element before the start of a.

      NB:jcannotbe replaced with -1, since doing that will cause Python to treat jas the lastelement of arather than the (nonexistent) element before a[0]. To get the desired behaviour, you must use -len(a)-1(or -(len(a)+1)) in place of j, which means that to get to a[j], slice starts at the last element of a, goes left for len(a)elements and then left one more element, ending up before astarts and thus including a[0]in the slice.

  • 如果ij为负数,则它们指的是从末尾开始的索引a(因此a[-1]指的是 的最后一个元素a
  • 如果i还是j没有指定,或者None,它们默认的两端a,但最终要看的迹象k

    • 如果k为正,则您正在向前切片,因此i变为 0 并j变为len(a)
    • 如果k是负数,你是向后切片,所以i成为len(a)j成为 开始之前的元素a

      注意:j不能用-1来代替,因为这样做会导致Python来治疗j作为最后的元素a,而不是以前的(不存在的)元素a[0]。要获得所需的行为,您必须使用-len(a)-1(或-(len(a)+1))代替j,这意味着要到达a[j],切片从 的最后一个元素开始a,向左移动len(a)元素,然后再留下一个元素,在a开始之前结束,因此包括a[0]在切片。

Therefore, a[:-1:-1]means "go from the end of a, which is a[-1](since iis unspecified and kis negative), to the last element of a(since j == -1), with step size of -1". iand jare equal – you start and stop slicing in the same place – so the expression evaluates to an empty list.

因此,a[:-1:-1]意思是“从端部去a,这是a[-1](因为i是不确定的,并且k是负的),到的最后一个元素a(自j == -1)中,用的步长-1”。iandj是相等的——你在同一个地方开始和停止切片——所以表达式的计算结果是一个空列表。

To reverse a[:-1], you can use a[-2::-1]. This way, the slice starts at the penultimate element, a[-2](since a[:-1]does not include a[-1]) and goes backwards until the element "before" a[0], meaning that a[0]is included in the slice.

要反转a[:-1],您可以使用a[-2::-1]. 这样,切片从倒数第二个元素开始a[-2](因为a[:-1]不包含a[-1])并向后移动直到元素“before” a[0],这意味着它a[0]包含在切片中。

>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:-1]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> a[-2::-1]
[8, 7, 6, 5, 4, 3, 2, 1, 0]

回答by Hemant Kapoor

In a simple way understand that if a[::-1]-1 at the end reverses the string.

以简单的方式理解 if 最后的a[::-1]-1 反转字符串。

Now

现在

a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
a[::-1]=[9, 8, 7, 6, 5, 4, 3, 2, 1, 0];

now a[:-1:-1]-1 in the middle doesn't make any sense because now it's the first element and this will give an empty list. Whereas a[-1::-1]gives you completed list and makes sense.

现在a[:-1:-1]中间的 -1 没有任何意义,因为现在它是第一个元素,这将给出一个空列表。而a[-1::-1]为您提供完整的列表并且有意义。