我有一个清单说,sample_list = [1,2,3,4,5,6,7]
。
现在,当我尝试访问时:
print(sample_list[-2:2])
或者,
print(sample_list[-3:-7])
在这两种情况下,我都会得到一个空列表。
它不应该至少[6,7]
或[5,6,7]
分别按照从左到右的约定打印吗?
我知道,我在语义上做错了。
(试图以从右到左的方向打印列表?)
我想了解空列表背后的逻辑。这里发生了什么?
我有一个清单说,sample_list = [1,2,3,4,5,6,7]
。
现在,当我尝试访问时:
print(sample_list[-2:2])
或者,
print(sample_list[-3:-7])
在这两种情况下,我都会得到一个空列表。
它不应该至少[6,7]
或[5,6,7]
分别按照从左到右的约定打印吗?
我知道,我在语义上做错了。
(试图以从右到左的方向打印列表?)
我想了解空列表背后的逻辑。这里发生了什么?
请记住,索引从 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]
如果你想从右到左切片,你需要提供一个否定的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)]
。差异仅在于某些值为负数或未提供时会发生什么。
处理负值的规则很简单(与非切片索引相同)。对于start
和stop
,只需将序列的长度添加到任何负值即可。因此,对于正x
和y
,切片L[-x:-y]
完全等价于L[len(L)-x:len(L)-y]
。负值step
不会被转换。
与常规索引不同,切片永远不会引发超出范围的索引异常。如果索引无效,您可能会得到一个空结果,或者只是比切片要求的值少。
并非切片的所有参数都是必需的。对象的slice
构造函数为未提供的任何参数分配None
默认值。这些None
s 的含义start
和stop
不同取决于 的符号step
,以及被切片的列表的维度。
If step
isNone
它总是被视为好像它是1
。如果step
是正数(或None
),则将 的start
值None
视为原样0
,将 的stop
值None
视为len(L)
。如果step
为负,则将 的start
值None
视为-1
,将 的stop
值None
视为-len(L)-1
。
所以,回到你的问题,当你做 slice 时sample_list[-2:2]
,会发生几件事:
首先,创建了一个slice
对象,就像您创建了slice(-2, 2)
. 该切片对象将具有step
of None
,因为您没有提供第三个值。
接下来,将slice
传递给列表并解释值。因为step
was None
,所以使用默认的1
。由于start
是负数,因此将列表的长度添加到其中。
最后,计算结果。对于具有七个值的示例列表,您将获得[sample_list[i] for i in range(5, 2, 1)]
. 由于范围是空的,所以切片也是。
根据您的需要,您可以通过几种不同的方式解决此问题。你可以保留它,你只会得到非常短的源列表的结果,其中len(L)-2
小于2
. 或者,您可以交换前两个参数的顺序,并得到结果[3,4,5]
。或者您可以添加一个负数step
并从右到左切片,从而得到[6, 5, 4]
.