0

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

现在,当我尝试访问时:

print(sample_list[-2:2])

或者,

print(sample_list[-3:-7])

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

它不应该至少[6,7][5,6,7]分别按照从左到右的约定打印吗?

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

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

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

4

2 回答 2

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]
于 2013-09-02T06:08:27.043 回答
4

如果你想从右到左切片,你需要提供一个否定的step: sample_list[-2:2:-1]。这也将颠倒值的顺序。

像这样的切片[-2:2]并不是没有意义的。如果你sample_list[-2: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默认值。这些Nones 的含义startstop不同取决于 的符号step,以及被切片的列表的维度。

If stepisNone它总是被视为好像它是1。如果step是正数(或None),则将 的startNone视为原样0,将 的stopNone视为len(L)。如果step为负,则将 的startNone视为-1,将 的stopNone视为-len(L)-1

所以,回到你的问题,当你做 slice 时sample_list[-2:2],会发生几件事:

首先,创建了一个slice对象,就像您创建了slice(-2, 2). 该切片对象将具有stepof None,因为您没有提供第三个值。

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

最后,计算结果。对于具有七个值的示例列表,您将获得[sample_list[i] for i in range(5, 2, 1)]. 由于范围是空的,所以切片也是。

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

于 2013-09-02T06:16:57.963 回答