什么是切片操作
在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[5:][5, 6, 7, 8, 9]>>> 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]
你可能还看不懂具体的语法(这正是本篇要介绍的),但你应该已经领略到了切片的花式操作。
写这篇文章的初衷是,一方面切片操作是Python中非常常见的,另一方面网上却很难找到全面系统的解析,比如以下结果是否让人有些迷惑:
>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[0::-1][0]>>> a[0:len(a):-1][]
为什么有len(a)和省略len(a)结果会不一样?
本文致力于真正讲清楚Python切片的使用方法。若您希望进一步了解切片的实现原理,以帮助我们自定义类的切片操作,敬请期待本文的续篇,《切片完全指南(原理篇)》。
基本索引
我们从Python的基本索引开始,即单个整数的索引。假设被索引的序列仍为之前提到的a,则基本索引的语法为a[index],其中index为下标。读者可能会觉得这里过于简单,但我们要强调的是Python一个语法糖:负数下标索引,即:index可以取为负数,当其为-n时,对倒数第n个元素进行索引。我们用一张表格值观展示a的索引范围。

非负下标索引和负数下标索引共同构成了Python索引的有效范围:。有效范围的概念对切片的理解非常重要,在基本索引中,索引超出有效范围时会抛出IndexError异常:
>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[10]Traceback (most recent call last):File "<stdin>", line 1, in <module>IndexError: list index out of range>>> a[-11]Traceback (most recent call last):File "<stdin>", line 1, in <module>IndexError: list index out of range
但在切片中不是这样,我们将在下文具体解释。
简单切片
简单切片指的是这样的切片形式:a[start:stop],其行为是得到下标在这样一个前闭后开区间范围内的元素,其中start和stop为负数时,简单看作是负数下标对应的位置即可:
>>> 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]
事情到这里也很简单,下面着重讲解两个比较特殊的情况:超出有效索引范围和缺省。
超出有效索引范围
当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][]
缺省
start和stop都是可以缺省的,在缺省的情况下,Python的行为是尽可能取最大区间,具体来说:
按照扩充索引范围的观点,start的缺省值是 无穷小(),stop的缺省值是 无穷大()。
>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[:5][0, 1, 2, 3, 4]>>> a[5:][5, 6, 7, 8, 9]>>> a[100:][]
扩展切片
早期的Python解释器仅支持上述a[start:stop]形式的基本切片,后来加入了下面要介绍的切片形式,扩展切片的名称也流传下来,实际上不用担心,这早已是Python所支持的标准语法。
扩展切片指的是这样的切片形式:a[start:stop:step],其中step是一个非零整数,即比简单切片多了调整步长的功能,此时切片的行为可概括为:从start对应的位置出发,以step为步长索引序列,直至越过stop对应的位置,且不包括stop本身。事实上,简单切片就是step=1的扩展切片的特殊情况。需要详细解释的是step分别为正数和负数的两种情况。
step为正数
当step为正数时,切片行为很容易理解,start和stop的截断和缺省规则也与简单切片完全一致:
>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[0:6:2][0, 2, 4]>>> a[::2][0, 2, 4, 6, 8]>>> a[:-2:2][0, 2, 4, 6]>>> a[4::2][4, 6, 8]
step为负数
当step为负数时,切片将其解释为从start出发以步长|step|逆序索引序列,此时,start和stop的截断依然遵循前述规则,但缺省发生一点变化,因为我们说过,在缺省的情况下,Python的行为是尽可能取最大区间,此时访问是逆序的,start应尽量取大,stop应尽量取小,才能保证区间最大,因此:
按照扩充索引范围的观点,start的缺省值是 无穷大(),stop的缺省值是 无穷小()
>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[5::-1][5, 4, 3, 2, 1, 0]>>> a[:4:-2][9, 7, 5]>>> a[::-1][9, 8, 7, 6, 5, 4, 3, 2, 1, 0]


















