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
Python list error: [::-1] step on [:-1] slice
提问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 -1
in a[:-1:-1]
doesn't mean what you think it does.
第一个-1
在a[:-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:1
is the shorthand for slice
object. slice
signature is slice(stop)
or slice(start, stop[, step])
and you can also use None
for arguments.
当您键入时,[1, 2, 3, ...][1:4:1]
它与[1, 2, 3, ...][slice(1, 4, 1)]
. object1:4:1
的简写也是如此slice
。slice
签名是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]
. 指数规则如下:
- First
c
is checked. Default is+1
, sign ofc
indicates forward or backward direction of the step. Absolute value ofc
indicates the step size. - Than
a
is checked. Whenc
is positive orNone
, default fora
is0
. Whenc
is negative, default fora
is-1
. - Finally
b
is checked. Whenc
is positive orNone
, default forb
islen
. Whenc
is negative default forb
is-(len+1)
.
- 首先
c
是检查。默认为+1
, 的符号c
表示步的前进或后退方向。的绝对值c
表示步长。 - 比
a
被检查。当c
为正或None
,默认a
就是0
。如果c
是负的,默认a
就是-1
。 - 最后
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
len
or0
. - an upper bound smaller than the lower bound returns an empty list or string or whatever else (for positive
c
).
- 将太大或太小的索引替换为
len
或0
。 - 小于下限的上限返回空列表或字符串或其他任何内容(对于 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 += c
on 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 range
produces a list
and xrange
can'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
slice
works similar to range
in that when you make the step
argument a negative number, the start
and stop
arguments work in the opposite direction.
slice
工作原理类似于range
当您使step
参数为负数时,start
和stop
参数以相反的方向工作。
>>> 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
i
orj
are negative, they refer to an index from the end ofa
(soa[-1]
refers to the last element ofa
) If
i
orj
are not specified, or areNone
, they default to the ends ofa
, but whichends depends on the sign ofk
:- if
k
is positive, you're slicing forwards, soi
becomes 0 andj
becomeslen(a)
if
k
is negative, you're slicing backwards, soi
becomeslen(a)
andj
becomes the element before the start ofa
.NB:
j
cannotbe replaced with -1, since doing that will cause Python to treatj
as the lastelement ofa
rather than the (nonexistent) element beforea[0]
. To get the desired behaviour, you must use-len(a)-1
(or-(len(a)+1)
) in place ofj
, which means that to get toa[j]
, slice starts at the last element ofa
, goes left forlen(a)
elements and then left one more element, ending up beforea
starts and thus includinga[0]
in the slice.
- if
- 如果
i
或j
为负数,则它们指的是从末尾开始的索引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 i
is unspecified and k
is negative), to the last element of a
(since j == -1
), with step size of -1". i
and j
are 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”。i
andj
是相等的——你在同一个地方开始和停止切片——所以表达式的计算结果是一个空列表。
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]
为您提供完整的列表并且有意义。