为什么列表从右到左方向切片返回空列表?

时间:2013-09-02 06:03:39

标签: python

我有一个名单,sample_list = [1,2,3,4,5,6,7]

现在,当我尝试访问时:

print(sample_list[-2:2])

,或者

print(sample_list[-3:-7])

在这两种情况下,我都会得到一个空列表。

不应该按照从左到右的惯例分别打印至少[6,7][5,6,7]

我知道,我在语义上做错了。

(尝试以从右到左的方向打印列表?)

我想了解空列表背后的逻辑。这里发生了什么?

2 个答案:

答案 0 :(得分:4)

请记住,索引从0开始:

sample_list = [1,2,3,4,5,6,7]
#              0 1 2 3 4 5 6

当你sample_list[-2:2]时,你正试图将第二个元素送到第三个元素。

但是你不能只是从消极到积极(除非你添加一个消极的步骤)。如果您希望获得反向列表,请添加step

>>> print sample_list[2:-2][::-1]
[5, 4, 3]

这与您的第二个示例存在同样的问题。你试图用负面指标向后退,但你不能......除非......你加入了一个消极的步骤!:

>>> print sample_list[-3:-7:-1]
[5, 4, 3, 2]

答案 1 :(得分:3)

如果您想从右向左切片,则需要提供否定的stepsample_list[-2:2:-1]。这也将颠倒值的顺序。

[-2:2]这样的切片并不是没有意义的。如果您在长度为2的列表上执行sample_list[-2:2],那么您将获得整件事的副本。在长度为3的列表中,您将获得仅包含中间元素的切片。它仅适用于长度为4或更大的列表,您将得到一个空切片。如果他们自动反转,那么其中一些案例就会模棱两可。

编辑:让我试着做一个更全面的解释。

Python的切片语法由slice个对象实现。也就是说,L[start:stop:step]相当于L[slice(start, stop, step)]。 (嗯,这就是它在Python 3中的工作原理。出于向后兼容性的原因,Python 2也有一种较旧的方法,使用__getslice____setslice__方法,但是使用slice对象的新方法可行太。)

当您获取切片或列表或元组时,始终会获得以索引start开头的元素,并一直持续到stop之前的元素。 step参数描述了所采取步骤的大小,2表示每隔一个值,而-1表示反向步骤。

另一种思考方式是切片L[start:stop:step]几乎等同于列表推导[L[i] for i in range(start, stop, step)]。差异仅在于某些值为负值或未提供时会发生的情况。

处理负值的规则很简单(并且与非切片索引相同)。对于startstop,只需将序列的长度添加到任何负值即可。因此,对于正xy,切片L[-x:-y]完全等同于L[len(L)-x:len(L)-y]。否定的step值不会被转换。

与常规索引不同,切片从不会引发索引超出范围的异常。如果索引无效,您可能会得到一个空结果,或者只是比切片要求的值少。

并非所有切片参数都是必需的。 slice对象的构造函数将None指定为未提供的任何参数的默认值。这些Nonestartstop的含义会有所不同,具体取决于step的符号,以及要切片的列表的维度。< / p>

如果stepNone,则始终将其视为1。如果step为正(或None),则start None值将被视为0stopNone被视为len(L)。如果step为否定,则startNone将被视为-1stopNone将被视为-len(L)-1 }。

因此,要回到您的问题,当您执行切片sample_list[-2:2]时,会发生以下几种情况:

首先,创建slice对象,就像您slice(-2, 2)一样。该切片对象的stepNone,因为您没有提供第三个值。

接下来,将slice传递给列表并解释值。由于stepNone,因此使用默认值1。由于start为负数,因此会将列表的长度添加到其中。

最后,计算出结果。对于包含七个值的示例列表,您将获得相当于[sample_list[i] for i in range(5, 2, 1)]的值。由于范围为空,因此切片也是如此。

根据您的需要,您可以通过几种不同的方式解决此问题。您可以保留它,并且您只能获得非常短的源列表的结果,其中len(L)-2小于2。或者,您可以交换前两个参数的顺序,并获得结果[3,4,5]。或者您可以从右到左添加否定的step和切片,从而生成[6, 5, 4]