Python切片

在Python中,切片(slice)是对序列型对象(如list, string, tuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素,而切片取出序列中一个范围对应的元素,这里的范围不是狭义上的连续片段。下面的代码初步展示了切片索引的力量。

>>> a=list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:5]
[0, 1, 2, 3, 4]
>>> a[2:8]
[2, 3, 4, 5, 6, 7]
>>> a[::2]
[0, 2, 4, 6, 8]
>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

切片语法

扩展切片指的是这样的切片形式:a[start:stop:step],其中step是一个非零整数,即比简单切片多了调整步长的功能,此时切片的行为可概括为:从start对应的位置出发,以step为步长索引序列,直至越过stop对应的位置,且不包括stop本身。事实上,简单切片就是step=1的扩展切片的特殊情况。需要详细解释的是step分别为正数和负数的两种情况。

简单切片

简单切片指的是这样的切片形式:a[start:stop],其行为是得到下标在这样一个前闭后开区间范围内的元素,其中startstop为负数时,简单看作是负数下标对应的位置即可:

>>> a=list(range(10))
 >>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[2:3]
 [2]
 >>> a[5:9]
 [5, 6, 7, 8]
 >>> a[5:-1]
 [5, 6, 7, 8]
 >>> a[-5:9]
 [5, 6, 7, 8]
 >>> a[-5:-1]
 [5, 6, 7, 8]

step为正数

step为正数时,切片行为很容易理解,startstop的截断和缺省规则也与简单切片完全一致:

>>> a=list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[0:5:1]
[0, 1, 2, 3, 4]
>>> a[0:5:2]
[0, 2, 4]
>>> a[0:5:3]
[0, 3]
>>> a[::2]
[0, 2, 4, 6, 8]
>>> a[:-2:2]
[0, 2, 4, 6]
>>> a[4:-2:2]
[4, 6]
>>>

step为负数

step为负数时,切片将其解释为从start出发以步长|step|逆序索引序列,此时,startstop截断依然遵循前述规则,但缺省发生一点变化,因为我们说过,在缺省的情况下,Python的行为是尽可能取最大区间,此时访问是逆序的,start应尽量取大,stop应尽量取小,才能保证区间最大,因此:

按照扩充索引范围的观点,start的缺省值是无穷大(​)stop的缺省值是无穷小(​)

>>> a=list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[0:5:-1]
[]
>>> a[0:5:-2]
[]
>>> a[0:5:-3]
[]
>>> a[::-2]
[9, 7, 5, 3, 1]
>>> a[:-2:-2]
[9]
>>> a[4:-2:-2]
[]
>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>>

缺省情况

为了深入理解step为缺省情况,来看下面一个示例:

 >>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[0::-1]
 [0]
 >>> a[0:len(a):-1]
 []

为什么有len(a)和省略len(a)结果会不一样?

根据上面的描述,可以做如下解释:

startstopstep(step缺省值为1)都是可以缺省的,在缺省的情况下,Python的行为是尽可能取最大区间,具体来说:

  • 当step>0时,按照扩充索引范围的观点,start的缺省值是无穷小(​)stop的缺省值是无穷大(​),才能保证区间最大
  • 当step<0时,按照扩充索引范围的观点,start的缺省值是无穷大(​)stop的缺省值是无穷小(​),才能保证区间最大
  • 当step=0时,报错:ValueError: slice step cannot be zero

提醒

当start或stop超出有效索引范围​时,切片操作不会抛出异常,而是进行截断。可以这样去理解截断机制:我们假象把索引范围扩充到全体整数,只不过小于​或大于​的区域对应空元素,在这个扩充后的数轴上进行切片,只需把最终结果中的所有空元素忽略即可。

来看几个具体的例子:

 >>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[-100:5]
 [0, 1, 2, 3, 4]
 >>> a[5:100]
 [5, 6, 7, 8, 9]
 >>> a[-100:100]
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[100:1000]
 []

另外,如果start的位置比stop还靠后怎么办?Python还是不会抛出异常,而是直接返回空序列:

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

slice()函数

实例

创建一个元组和一个 slice 对象。使用 slice 对象仅获取元组的前两项:

>>> a = ("a", "b", "c", "d", "e", "f", "g", "h")
>>> x = slice(2)
>>> x
slice(None, 2, None)
>>> a[x]
('a', 'b')
>>>

定义和用法

slice() 函数返回 slice 对象(切片)。

slice 对象用于指定如何对序列进行裁切。您可以指定在哪里开始裁切以及在哪里结束裁切。您还可以指定步进,例如只切每隔一个项目。

语法

slice(start, end, step)

参数值

参数|描述 start|可选。整数,指定在哪个位置开始裁切。默认为 0。 end|可选。整数,指定在哪个位置结束裁切。 step|可选。整数,指定裁切的步进值。默认为 1。

更多实例

【例】创建一个元组和一个切片对象,并返回结果:

>>> a = ("a", "b", "c", "d", "e", "f", "g", "h")
>>> x = slice(2)
>>> x
slice(None, 2, None)
>>> a[x]
('a', 'b')
>>> x = slice(3,5)
>>> x
slice(3, 5, None)
>>> a[x]
('d', 'e')
>>> x = slice(3,5,-1)
>>> a[x]
()
>>> x = slice(3,5,2)
>>> a[x]
('d',)
>>>