Python中使用切片 [ : 0:-1] 反转列表

5
我很困惑Python中的列表切片。
对于列表:
L=[0,1,2,3,4,5,6,7,8,9,10]

我想把列表反转,可以通过以下方法获得答案:

L[::-1] 

获得 [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

然而,当我尝试

L[10:0:-1]

我得到了一个没有0的列表[10,9,8,7,6,5,4,3,2,1]L[10:1:-1]L[10:-1:-1]都无法给出答案。
另一方面,L[200::-1]L[10:-12:-1]给出正确的答案,尽管L[200]L[-12]超出了范围。
我想了解Python在这种情况下的基本逻辑。谢谢。

L[10::-1]同样有效。 - Jason Sperske
1
这是一个比我更好的答案:https://dev59.com/D3RB5IYBdhLWcg3wyqOo#509295 基本上,中间的参数是从右边算起的元素数量-1。 - Jason Sperske
关于“越界”索引:如果切片索引超出列表的大小,Python 只会取尽可能多的可用元素(即整个列表)。 - Matt Clarke
可能是Python的切片符号的重复问题。 - Michael Foukarakis
类似问题:为什么 'L [nn:0:-1]' 和 'L [nn ::- 1]' 不等价(其中 nn = len(L))? - berniethejet
4个回答

5
让我们以列表为例,
a = [1, 2, 3, 4, 4, 5, 6, 9]

如果你试图使用正数索引来切分它,
newa = a[1:5] 

这将导致:
newa = [2, 3, 4, 4] 

这是因为,在以上情况下,切片发生在这样的方式,a[inclusive : exclusive],第一个索引被包含在内,并从此索引开始切片,一直到(5)索引之前的位置,即不包括(记住)。这只是列表切片工作的方式。

要获取列表a的最后两个值,

newa = [6 : ]

在这里,索引从6(包括)开始,一直到列表的末尾。

如果您热衷于在列表中使用负索引,因为Python提供了简化索引的功能,请彻底了解切片的包含和不包含的问题。

对于上面的示例,要使用负索引获取列表的最后两个数字,我们需要做的是:

newa = a[-2 : ]

在正向索引的情况下,索引从0开始,而在负向索引的情况下,索引为-1、-2等。因此,在上面的示例中,从列表中倒数第二个数字开始,切片到列表的末尾是所理解的。

现在,要反转列表,可以执行以下操作:

print a.reverse()
[9, 6, 5, 4, 4, 3, 2, 1]

在切片方式中,可以通过给定[start,end,step]来反转列表,就像上面提到的那样,但我想进一步澄清。
 r = a[2: : -1]

这会创建一个新的列表,从索引2开始并一直到列表结尾,但由于步幅是-1,我们从索引2递减,直到达到0。因此,我们得到了以下反转的前三个数字列表:
r = [3, 2, 1]

此外,要将整个列表反转,
r = a[len(a): : -1]

这将从8开始,列表的长度为8,但是在索引术语中,它从0开始,我们有0到8个索引,因此从第8个索引开始,每次递减1步,直到列表的结尾。结果如下:

[9, 6, 5, 4, 4, 3, 2, 1]

我个人喜欢使用这种方法来反转列表。


3
对于Python列表切片语法,list[start:end:step]将获取一个切片列表,其中项目从list[start]开始,但list[end]被排除在外。 因此,在您的情况下,L[10:0:-1]将排除L[0],即0,而L[10::-1]将按您的预期工作。
startend为负数时,它表示从列表末尾开始计数。因此,list[-1]将获取列表中的最后一项。 在您的情况下,L[10:-1:-1]等同于L[10:10:-1]。 因此,L[10:-1:-1]将获取[]

2
 >>> L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 >>> L[1:3]
 [1, 2]

索引3是不包括的。

>>> L[0:10:1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

索引10是排除在外的,如果您想选择所有内容,应使用:

>>>L[0:11:1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

但是你无法获取L[11],因为它会抛出IndexError,因为你只有11个元素,最大索引是10。原因是L[0:11:1]不会越界,因为这个切片只访问索引0到10的元素,而不包括L[11]

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

-1 是切片反向步骤, 0 表示不包括切片起始位置。

L[10:-1:-1] 等同于 L[10:10:-1] ,因为第一个 -1 表示 L 的最后一个索引。

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

索引 -11 相当于索引 0,索引 -12 相当于索引 0 之前的索引


1
以上答案正确地解释了列表切片的工作原理。然而,我想谈一下问题的最后部分——即使200和12都超出了数组的范围,L[200::-1]L[10:-12:-1]是如何工作的?
你可以简单地理解为,当使用切片从序列中提取元素时,Python 确保切片中使用的索引在序列的长度范围内。因此,在您的情况下,当您指定 L[200::-1] 时,Python 内部会检查序列 L 的长度仅为11,因此将上述语句视为 L[10::-1]。类似的论点适用于 L[10:-12:-1]此链接 提供了关于区间切片的良好见解。通常在该页面的末尾有一个描述,并且有一个关于如何实现支持扩展切片的序列的示例。引用如下:

现在切片对象有一个方法indices(length),给定序列的长度,返回一个(start, stop, step)元组,可以直接传递给range()。indices()处理省略和越界索引的方式与常规切片一致(这个无害的短语隐藏了一堆令人困惑的细节!)。


你是否真的需要检查任何东西,还是只是应用min/max? - berniethejet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接